Skip to content

Commit a3e41a4

Browse files
committed
Add dedicated setup type for SetupAllProperties
1 parent 5db2a42 commit a3e41a4

File tree

5 files changed

+115
-48
lines changed

5 files changed

+115
-48
lines changed

src/Moq/Mock.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -611,7 +611,7 @@ private static TSetup SetupRecursive<TSetup>(Mock mock, LambdaExpression origina
611611

612612
internal static void SetupAllProperties(Mock mock)
613613
{
614-
// TODO: implement!
614+
mock.MutableSetups.Add(new StubbedPropertiesSetup(mock));
615615
}
616616

617617
#endregion

src/Moq/MockDefaultValueProvider.cs

+4
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,10 @@ protected override object GetFallbackDefaultValue(Type type, Mock mock)
3636
var mockType = typeof(Mock<>).MakeGenericType(type);
3737
Mock newMock = (Mock)Activator.CreateInstance(mockType, mock.Behavior);
3838
newMock.DefaultValueProvider = mock.DefaultValueProvider;
39+
if (mock.MutableSetups.FindLast(s => s is StubbedPropertiesSetup) is StubbedPropertiesSetup sts)
40+
{
41+
newMock.MutableSetups.Add(new StubbedPropertiesSetup(newMock, sts.DefaultValueProvider));
42+
}
3943
if(!type.IsDelegateType())
4044
{
4145
newMock.CallBase = mock.CallBase;

src/Moq/StubbedPropertiesSetup.cs

+110
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
// Copyright (c) 2007, Clarius Consulting, Manas Technology Solutions, InSTEDD, and Contributors.
2+
// All rights reserved. Licensed under the BSD 3-Clause License; see License.txt.
3+
4+
using System.Collections.Generic;
5+
using System.Diagnostics;
6+
using System.Linq.Expressions;
7+
8+
using E = System.Linq.Expressions.Expression;
9+
10+
namespace Moq
11+
{
12+
internal sealed class StubbedPropertiesSetup : Setup
13+
{
14+
private readonly Dictionary<string, object> values;
15+
private readonly DefaultValueProvider defaultValueProvider;
16+
17+
public StubbedPropertiesSetup(Mock mock, DefaultValueProvider defaultValueProvider = null)
18+
: base(originalExpression: null, mock, new PropertyAccessorExpectation(mock))
19+
{
20+
this.values = new Dictionary<string, object>();
21+
this.defaultValueProvider = defaultValueProvider ?? mock.DefaultValueProvider;
22+
23+
this.MarkAsVerifiable();
24+
}
25+
26+
public DefaultValueProvider DefaultValueProvider => this.defaultValueProvider;
27+
28+
public override IEnumerable<Mock> InnerMocks
29+
{
30+
get
31+
{
32+
foreach (var value in this.values.Values)
33+
{
34+
var innerMock = TryGetInnerMockFrom(value);
35+
if (innerMock != null)
36+
{
37+
yield return innerMock;
38+
}
39+
}
40+
}
41+
}
42+
43+
public void SetProperty(string propertyName, object value)
44+
{
45+
this.values[propertyName] = value;
46+
}
47+
48+
protected override void ExecuteCore(Invocation invocation)
49+
{
50+
if (invocation.Method.ReturnType == typeof(void))
51+
{
52+
Debug.Assert(invocation.Method.IsSetAccessor());
53+
Debug.Assert(invocation.Arguments.Length == 1);
54+
55+
var propertyName = invocation.Method.Name.Substring(4);
56+
this.values[propertyName] = invocation.Arguments[0];
57+
}
58+
else
59+
{
60+
Debug.Assert(invocation.Method.IsGetAccessor());
61+
62+
var propertyName = invocation.Method.Name.Substring(4);
63+
if (!this.values.TryGetValue(propertyName, out var value))
64+
{
65+
value = this.values[propertyName] = this.Mock.GetDefaultValue(invocation.Method, out _, this.defaultValueProvider);
66+
}
67+
68+
invocation.ReturnValue = value;
69+
}
70+
}
71+
72+
protected override void VerifySelf()
73+
{
74+
}
75+
76+
private sealed class PropertyAccessorExpectation : Expectation
77+
{
78+
private readonly LambdaExpression expression;
79+
80+
public PropertyAccessorExpectation(Mock mock)
81+
{
82+
Debug.Assert(mock != null);
83+
84+
var mockType = mock.GetType();
85+
var mockedType = mockType.GetGenericArguments()[0];
86+
var mockGetMethod = Mock.GetMethod.MakeGenericMethod(mockedType);
87+
var setupAllPropertiesMethod = mockType.GetMethod(nameof(Mock<object>.SetupAllProperties));
88+
var mockParam = E.Parameter(mockedType, "m");
89+
this.expression = E.Lambda(E.Call(E.Call(mockGetMethod, mockParam), setupAllPropertiesMethod), mockParam);
90+
}
91+
92+
public override LambdaExpression Expression => this.expression;
93+
94+
public override bool Equals(Expectation other)
95+
{
96+
return other is PropertyAccessorExpectation pae && ExpressionComparer.Default.Equals(this.expression, pae.expression);
97+
}
98+
99+
public override int GetHashCode()
100+
{
101+
return typeof(PropertyAccessorExpectation).GetHashCode();
102+
}
103+
104+
public override bool IsMatch(Invocation invocation)
105+
{
106+
return invocation.Method.IsPropertyAccessor();
107+
}
108+
}
109+
}
110+
}

tests/Moq.Tests/SetupFixture.cs

-26
Original file line numberDiff line numberDiff line change
@@ -139,15 +139,6 @@ public void OriginalExpression_equal_to_Expression_for_simple_method_call()
139139
Assert.Equal(setup.Expression, setup.OriginalExpression, ExpressionComparer.Default);
140140
}
141141

142-
[Fact]
143-
public void OriginalExpression_equal_to_Expression_for_simple_expression_in_Mock_Of()
144-
{
145-
var mockObject = Mock.Of<IX>(m => m.Property == null);
146-
var setup = Mock.Get(mockObject).Setups.First();
147-
148-
Assert.Equal(setup.Expression, setup.OriginalExpression, ExpressionComparer.Default);
149-
}
150-
151142
[Fact]
152143
public void OriginalExpression_returns_expression_different_from_Expression_for_multi_dot_expression()
153144
{
@@ -178,23 +169,6 @@ public void OriginalExpression_returns_whole_multi_dot_expression()
178169
Assert.Equal(originalExpression, setup.OriginalExpression, ExpressionComparer.Default);
179170
}
180171

181-
[Fact]
182-
public void OriginalExpression_returns_only_left_hand_side_of_expression_in_Mock_Of()
183-
{
184-
Expression<Func<IX, string>> originalExpressionLeftHandSide = m => m.Inner[1].ToString();
185-
Expression<Func<IX, bool>> mockSpecification =
186-
Expression.Lambda<Func<IX, bool>>(
187-
Expression.MakeBinary(
188-
ExpressionType.Equal,
189-
originalExpressionLeftHandSide.Body,
190-
Expression.Constant("")),
191-
originalExpressionLeftHandSide.Parameters);
192-
var mockObject = Mock.Of<IX>(mockSpecification);
193-
var setup = Mock.Get(mockObject).Setups.First();
194-
195-
Assert.Equal(originalExpressionLeftHandSide, setup.OriginalExpression, ExpressionComparer.Default);
196-
}
197-
198172
[Fact]
199173
public void OriginalExpression_same_for_all_partial_setups_resulting_from_it()
200174
{

tests/Moq.Tests/SetupsFixture.cs

-21
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,6 @@ public void Mock_made_with_new_operator_initially_has_no_setups()
1818
Assert.Empty(mock.Setups);
1919
}
2020

21-
[Fact]
22-
public void Mock_made_with_Mock_Of_without_an_expression_initially_has_no_setups()
23-
{
24-
var mockObject = Mock.Of<object>();
25-
var mock = Mock.Get(mockObject);
26-
Assert.Empty(mock.Setups);
27-
}
28-
2921
[Fact]
3022
public void Setup_adds_one_setup_with_same_expression_to_Setups()
3123
{
@@ -38,19 +30,6 @@ public void Setup_adds_one_setup_with_same_expression_to_Setups()
3830
Assert.Equal(setupExpression, setup.Expression, ExpressionComparer.Default);
3931
}
4032

41-
[Fact]
42-
public void Mock_Of_with_expression_for_a_single_member_adds_one_setup_with_same_but_only_partial_expression_to_Setups()
43-
{
44-
Expression<Func<object, bool>> mockSpecification = m => m.ToString() == default(string);
45-
Expression<Func<object, string>> setupExpression = m => m.ToString();
46-
47-
var mockObject = Mock.Of<object>(mockSpecification);
48-
var mock = Mock.Get(mockObject);
49-
50-
var setup = Assert.Single(mock.Setups);
51-
Assert.Equal(setupExpression, setup.Expression, ExpressionComparer.Default);
52-
}
53-
5433
[Fact]
5534
public void Mock_Reset_results_in_empty_Setups()
5635
{

0 commit comments

Comments
 (0)