Skip to content

Commit 3f4264d

Browse files
authored
Layer SubstituteForBuilder on top of AutoSubstituteBuilder (#48)
This greatly simplifies some of the registration code as now there is no need to call .Configure(...) or .Configured() to continue registering other types. Since .Configured() was never released publicly, this is now removed, while .Configure(...) is obsoleted with a new API .ConfigureSubsitute introduced which returns the current SubstituteForBuilder. The new succinct syntax is much more fluid, and doesn't break currently built tests.
1 parent 7fa6c29 commit 3f4264d

File tree

7 files changed

+72
-45
lines changed

7 files changed

+72
-45
lines changed

AutofacContrib.NSubstitute.Tests/AutoSubstituteOptionsFixture.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ public void InternalConstructorSucceeds()
113113
public void BaseCalledByDefault()
114114
{
115115
using var mock = AutoSubstitute.Configure()
116-
.SubstituteForPartsOf<ClassWithBase>().Configured()
116+
.SubstituteForPartsOf<ClassWithBase>()
117117
.Build()
118118
.Container;
119119

@@ -124,7 +124,7 @@ public void BaseCalledByDefault()
124124
public void BaseCallDisabled()
125125
{
126126
using var mock = AutoSubstitute.Configure()
127-
.SubstituteForPartsOf<ClassWithBase>().DoNotCallBase().Configured()
127+
.SubstituteForPartsOf<ClassWithBase>().DoNotCallBase()
128128
.Build()
129129
.Container;
130130

AutofacContrib.NSubstitute.Tests/ExampleFixture.cs

+2-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
using Autofac;
22
using NSubstitute;
3-
using NSubstitute.Extensions;
43
using NUnit.Framework;
4+
using System;
55

66
namespace AutofacContrib.NSubstitute.Tests
77
{
@@ -167,16 +167,15 @@ public void Example_test_with_concrete_object_provided()
167167
}
168168

169169
[Test]
170+
[Obsolete]
170171
public void Example_test_with_substitute_for_concrete_resolved_from_autofac()
171172
{
172173
const int val1 = 2;
173174
const int val2 = 3;
174175
const int val3 = 4;
175176

176-
#pragma warning disable CS0618 // Type or member is obsolete
177177
using var mock = AutoSubstitute.Configure()
178178
.ResolveAndSubstituteFor<ConcreteClassWithDependency>(new TypedParameter(typeof(int), val1))
179-
#pragma warning restore CS0618 // Type or member is obsolete
180179
.Build();
181180

182181
mock.Resolve<IDependency2>().SomeOtherMethod().Returns(val2);

AutofacContrib.NSubstitute.Tests/SubstituteForFixture.cs

+28-10
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ namespace AutofacContrib.NSubstitute.Tests
1010
public class SubstituteForFixture
1111
{
1212
[Test]
13-
public void Example_test_with_substitute_for_concrete()
13+
[Obsolete]
14+
public void Example_test_with_substitute_for_concrete_obsolete()
1415
{
1516
const int val1 = 3;
1617
const int val2 = 2;
@@ -27,14 +28,32 @@ public void Example_test_with_substitute_for_concrete()
2728
Assert.That(result, Is.EqualTo(val3));
2829
}
2930

31+
[Test]
32+
public void Example_test_with_substitute_for_concrete()
33+
{
34+
const int val1 = 3;
35+
const int val2 = 2;
36+
const int val3 = 10;
37+
38+
using var utoSubstitute = AutoSubstitute.Configure()
39+
.SubstituteFor<ConcreteClass>(val2).ConfigureSubstitute(c => c.Add(Arg.Any<int>()).Returns(val3))
40+
.Build();
41+
42+
utoSubstitute.Resolve<IDependency2>().SomeOtherMethod().Returns(val1);
43+
44+
var result = utoSubstitute.Resolve<MyClassWithConcreteDependency>().AMethod();
45+
46+
Assert.That(result, Is.EqualTo(val3));
47+
}
48+
3049
[Test]
3150
public void SubstituteForConfigureWithContext()
3251
{
3352
const int val = 2;
3453

3554
using var utoSubstitute = AutoSubstitute.Configure()
36-
.SubstituteFor<ConcreteClass>(val).Configured()
37-
.SubstituteFor<ConcreteClassWithObject>().Configure((s, ctx) =>
55+
.SubstituteFor<ConcreteClass>(val)
56+
.SubstituteFor<ConcreteClassWithObject>().ConfigureSubstitute((s, ctx) =>
3857
{
3958
s.Configure().GetResult().Returns(ctx.Resolve<ConcreteClass>());
4059
})
@@ -50,7 +69,7 @@ public void SubstituteForConfigureWithContext()
5069
public void BaseCalledOnSubstituteForPartsOf()
5170
{
5271
using var mock = AutoSubstitute.Configure()
53-
.SubstituteForPartsOf<Test1>().Configured()
72+
.SubstituteForPartsOf<Test1>()
5473
.Build();
5574

5675
var test1 = mock.Resolve<Test1>();
@@ -63,7 +82,7 @@ public void BaseCalledOnSubstituteForPartsOf()
6382
public void BaseNotCalledOnSubstituteFor()
6483
{
6584
using var mock = AutoSubstitute.Configure()
66-
.SubstituteFor<Test1>().Configured()
85+
.SubstituteFor<Test1>()
6786
.Build();
6887

6988
var test1 = mock.Resolve<Test1>();
@@ -76,7 +95,7 @@ public void BaseNotCalledOnSubstituteFor()
7695
public void FailsIfSubstituteTypeIsChanged()
7796
{
7897
var builder = AutoSubstitute.Configure()
79-
.SubstituteFor<Test1>().Configured();
98+
.SubstituteFor<Test1>();
8099

81100
Assert.Throws<InvalidOperationException>(() => builder.SubstituteForPartsOf<Test1>());
82101
}
@@ -85,7 +104,7 @@ public void FailsIfSubstituteTypeIsChanged()
85104
public void FailsIfSubstituteTypeIsChanged2()
86105
{
87106
var builder = AutoSubstitute.Configure()
88-
.SubstituteForPartsOf<Test1>().Configured();
107+
.SubstituteForPartsOf<Test1>();
89108

90109
Assert.Throws<InvalidOperationException>(() => builder.SubstituteFor<Test1>());
91110
}
@@ -95,7 +114,7 @@ public void PropertiesNotSetByDefault()
95114
{
96115
using var mock = AutoSubstitute.Configure()
97116
.Provide<IProperty, CustomProperty>(out _)
98-
.SubstituteFor<TestWithProperty>().Configured()
117+
.SubstituteFor<TestWithProperty>()
99118
.Build();
100119

101120
Assert.IsNull(mock.Resolve<TestWithProperty>().PropertySetter);
@@ -109,7 +128,6 @@ public void PropertiesSetIfRequested()
109128
.Provide<IProperty, CustomProperty>(out var property)
110129
.SubstituteFor<TestWithProperty>()
111130
.InjectProperties()
112-
.Configured()
113131
.Build();
114132

115133
Assert.AreEqual(property.Value, mock.Resolve<TestWithProperty>().PropertySetter);
@@ -122,7 +140,7 @@ public void PropertiesSetIfGloballyRequested()
122140
using var mock = AutoSubstitute.Configure()
123141
.InjectProperties()
124142
.Provide<IProperty, CustomProperty>(out var property)
125-
.SubstituteFor<TestWithProperty>().Configured()
143+
.SubstituteFor<TestWithProperty>()
126144
.Build();
127145

128146
Assert.AreEqual(property.Value, mock.Resolve<TestWithProperty>().PropertySetter);

AutofacContrib.NSubstitute/AutoSubstituteBuilder.cs

+16-1
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,28 @@ public class AutoSubstituteBuilder
1414
private readonly ContainerBuilder _builder;
1515
private readonly AutoSubstituteOptions _options;
1616

17+
/// <summary>
18+
/// Create a new instance of the builder.
19+
/// </summary>
1720
public AutoSubstituteBuilder()
1821
{
1922
_substituteForRegistrations = new Dictionary<Type, object>();
2023
_afterBuildActions = new List<Action<IComponentContext>>();
2124
_builder = new ContainerBuilder();
2225
_options = new AutoSubstituteOptions();
2326
}
27+
28+
/// <summary>
29+
/// Creates a new instance that allows linking to the previous instance for derived builders.
30+
/// </summary>
31+
/// <param name="other">A <see cref="AutoSubstituteBuilder"/> that should be connected to this instance</param>
32+
private protected AutoSubstituteBuilder(AutoSubstituteBuilder other)
33+
{
34+
_substituteForRegistrations = other._substituteForRegistrations;
35+
_afterBuildActions = other._afterBuildActions;
36+
_builder = other._builder;
37+
_options = other._options;
38+
}
2439

2540
/// <summary>
2641
/// Builds an <see cref="AutoSubstitute"/> from the current builder.
@@ -274,7 +289,7 @@ private SubstituteForBuilder<TService> CreateSubstituteForBuilder<TService>(Func
274289
return builder;
275290
}
276291

277-
internal IProvidedValue<TService> CreateProvidedValue<TService>(Func<IComponentContext, TService> factory)
292+
private protected IProvidedValue<TService> CreateProvidedValue<TService>(Func<IComponentContext, TService> factory)
278293
{
279294
var value = new ProvidedValue<TService>(factory);
280295

AutofacContrib.NSubstitute/SubstituteForBuilder.cs

+16-12
Original file line numberDiff line numberDiff line change
@@ -2,25 +2,25 @@
22
using Autofac.Builder;
33
using NSubstitute.Core;
44
using System;
5+
using System.ComponentModel;
56

67
namespace AutofacContrib.NSubstitute
78
{
89
/// <summary>
910
/// A class to configure substituted services.
1011
/// </summary>
1112
/// <typeparam name="TService">The type of the substituted service.</typeparam>
12-
public class SubstituteForBuilder<TService>
13+
public class SubstituteForBuilder<TService> : AutoSubstituteBuilder
1314
where TService : class
1415
{
15-
private readonly AutoSubstituteBuilder _builder;
1616
private readonly IRegistrationBuilder<TService, SimpleActivatorData, SingleRegistrationStyle> _registration;
1717

1818
internal SubstituteForBuilder(
1919
AutoSubstituteBuilder builder,
2020
IRegistrationBuilder<TService, SimpleActivatorData, SingleRegistrationStyle> registration,
2121
bool isSubstituteFor)
22+
: base(builder)
2223
{
23-
_builder = builder;
2424
_registration = registration;
2525
IsSubstituteFor = isSubstituteFor;
2626
}
@@ -37,28 +37,32 @@ internal SubstituteForBuilder(
3737
/// </summary>
3838
/// <param name="action">The delegate to configure the service.</param>
3939
/// <returns>The original <see cref="AutoSubstituteBuilder"/>.</returns>
40+
[Obsolete("Use ConfigureSubstitute instead")]
41+
[EditorBrowsable(EditorBrowsableState.Never)]
4042
public AutoSubstituteBuilder Configure(Action<TService> action)
41-
=> Configure((s, _) => action(s));
43+
=> ConfigureSubstitute((s, _) => action(s));
44+
45+
/// <summary>
46+
/// Allows for configuration of the service.
47+
/// </summary>
48+
/// <param name="action">The delegate to configure the service.</param>
49+
/// <returns>The original <see cref="AutoSubstituteBuilder"/>.</returns>
50+
public SubstituteForBuilder<TService> ConfigureSubstitute(Action<TService> action)
51+
=> ConfigureSubstitute((s, _) => action(s));
4252

4353
/// <summary>
4454
/// Allows for configuration of the service with access to the resolved components.
4555
/// </summary>
4656
/// <param name="action">The delegate to configure the service.</param>
4757
/// <returns>The original <see cref="AutoSubstituteBuilder"/>.</returns>
48-
public AutoSubstituteBuilder Configure(Action<TService, IComponentContext> action)
58+
public SubstituteForBuilder<TService> ConfigureSubstitute(Action<TService, IComponentContext> action)
4959
{
5060
_registration.OnActivated(args =>
5161
{
5262
action(args.Instance, args.Context.Resolve<IComponentContext>());
5363
});
5464

55-
return _builder;
65+
return this;
5666
}
57-
58-
/// <summary>
59-
/// Completes the configuration of the substitute.
60-
/// </summary>
61-
/// <returns>The original <see cref="AutoSubstituteBuilder"/>.</returns>
62-
public AutoSubstituteBuilder Configured() => _builder;
6367
}
6468
}

AutofacContrib.NSubstitute/SubstituteForBuilderExtensions.cs

+2-10
Original file line numberDiff line numberDiff line change
@@ -13,27 +13,19 @@ public static class SubstituteForBuilderExtensions
1313
/// <returns></returns>
1414
public static SubstituteForBuilder<T> DoNotCallBase<T>(this SubstituteForBuilder<T> builder)
1515
where T : class
16-
{
17-
builder.Configure(t =>
16+
=> builder.ConfigureSubstitute(t =>
1817
{
1918
var router = SubstitutionContext.Current.GetCallRouterFor(t);
2019

2120
router.CallBaseByDefault = false;
2221
});
2322

24-
return builder;
25-
}
26-
2723
public static SubstituteForBuilder<T> InjectProperties<T>(this SubstituteForBuilder<T> builder)
2824
where T : class
29-
{
30-
builder.Configure((t, ctx) =>
25+
=> builder.ConfigureSubstitute((t, ctx) =>
3126
{
3227
ctx.InjectUnsetProperties(t);
3328
AutoPropertyInjectorMockHandler.Instance.OnMockCreated(t, typeof(T), ctx, builder.Context);
3429
});
35-
36-
return builder;
37-
}
3830
}
3931
}

README.md

+6-7
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ public void Example_test_with_substitute_for_concrete()
164164
const int val2 = 2;
165165
const int val3 = 10;
166166
using var autoSubstitute = AutoSubstitute.Configure()
167-
.SubstituteFor<ConcreteClass>(val2).Configure(c => c.Add(Arg.Any<int>()).Returns(val3))
167+
.SubstituteFor<ConcreteClass>(val2).ConfigureSubstitute(c => c.Add(Arg.Any<int>()).Returns(val3))
168168
.Build();
169169
autoSubstitute.Resolve<IDependency2>().SomeOtherMethod().Returns(val1);
170170

@@ -183,8 +183,8 @@ public void SubstituteForConfigureWithContext()
183183
const int val = 2;
184184

185185
using var utoSubstitute = AutoSubstitute.Configure()
186-
.SubstituteFor<ConcreteClass>(val).Configured()
187-
.SubstituteFor<ConcreteClassWithObject>().Configure((s, ctx) =>
186+
.SubstituteFor<ConcreteClass>(val)
187+
.SubstituteFor<ConcreteClassWithObject>().ConfigureSubstitute((s, ctx) =>
188188
{
189189
s.Configure().GetResult().Returns(ctx.Resolve<ConcreteClass>());
190190
})
@@ -209,7 +209,7 @@ public abstract class Test1
209209
public void BaseCalledOnSubstituteForPartsOf()
210210
{
211211
using var mock = AutoSubstitute.Configure()
212-
.SubstituteForPartsOf<Test1>().Configured()
212+
.SubstituteForPartsOf<Test1>()
213213
.Build();
214214

215215
var test1 = mock.Resolve<Test1>();
@@ -230,7 +230,7 @@ public abstract class Test1
230230
public void BaseCalledOnSubstituteForPartsOf()
231231
{
232232
using var mock = AutoSubstitute.Configure()
233-
.SubstituteForPartsOf<Test1>().DoNotCallBase().Configured()
233+
.SubstituteForPartsOf<Test1>().DoNotCallBase()
234234
.Build();
235235

236236
var test1 = mock.Resolve<Test1>();
@@ -249,7 +249,6 @@ public void PropertiesSetIfRequested()
249249
.Provide<IProperty, CustomProperty>(out var property)
250250
.SubstituteFor<TestWithProperty>()
251251
.InjectProperties()
252-
.Configured()
253252
.Build();
254253

255254
Assert.AreEqual(property.Value, mock.Resolve<TestWithProperty>().PropertySetter);
@@ -262,7 +261,7 @@ public void PropertiesSetIfGloballyRequested()
262261
using var mock = AutoSubstitute.Configure()
263262
.InjectProperties()
264263
.Provide<IProperty, CustomProperty>(out var property)
265-
.SubstituteFor<TestWithProperty>().Configured()
264+
.SubstituteFor<TestWithProperty>()
266265
.Build();
267266

268267
Assert.AreEqual(property.Value, mock.Resolve<TestWithProperty>().PropertySetter);

0 commit comments

Comments
 (0)