Skip to content

Commit 9d87c2c

Browse files
RLittlesIIrsg-bot
andauthored
feature: add a lazy builder method to AutoFixtureBase (#1940)
* feature: add a lazy builder method to AutoFixtureBase * test the new concern fix weird issue with global namespace * Automatically linting code --------- Co-authored-by: Rocket Understudy <33589210+rsg-bot@users.noreply.github.com>
1 parent 8318a03 commit 9d87c2c

9 files changed

Lines changed: 334 additions & 151 deletions

src/Testing.AutoFixtures/AutoFixtureBase.cs

Lines changed: 164 additions & 137 deletions
Large diffs are not rendered by default.

src/Testing.AutoFixtures/AutoFixtureGenerator.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ Compilation compilation
5959
var usingDirectives = new HashSet<string>(
6060
parameterSymbols
6161
.Select(symbol => symbol.Type.ContainingNamespace?.ToDisplayString() ?? "")
62-
.Where(x => !string.IsNullOrWhiteSpace(x))
62+
.Where(containingNamespace => !string.IsNullOrWhiteSpace(containingNamespace) && containingNamespace != "<global namespace>")
6363
.Distinct()
6464
)
6565
{

test/Testing.AutoFixtures.Tests/AutoFixtureGeneratorTests.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ public async Task GivenAutoFixture_WhenGenerate_ThenShouldGenerateAutoFixtureBas
5555
[MemberData(nameof(UsingTypeNamespaceSourceData.Data), MemberType = typeof(UsingTypeNamespaceSourceData))]
5656
[MemberData(nameof(NestedClassFixtureData.Data), MemberType = typeof(NestedClassFixtureData))]
5757
[MemberData(nameof(DifferentNamedFixtureData.Data), MemberType = typeof(DifferentNamedFixtureData))]
58+
[MemberData(nameof(LazyConstructorFixtureData.Data), MemberType = typeof(LazyConstructorFixtureData))]
5859
public async Task GivenAutoFixtureAttribute_WhenGenerate_ThenGeneratesAutoFixture(
5960
GeneratorTestContext context
6061
)
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
using FakeItEasy;
2+
3+
using NSubstitute;
4+
5+
using Rocket.Surgery.Extensions.Testing.SourceGenerators;
6+
7+
namespace Rocket.Surgery.Extensions.Testing.AutoFixtures.Tests;
8+
9+
internal class LazyConstructorFixtureData : AutoFixtureSourceData
10+
{
11+
public static TheoryData<GeneratorTestContext> Data =>
12+
[
13+
DefaultBuilder()
14+
.AddReferences(typeof(Fake))
15+
.AddSources(Source, IThing, AttributedFixtureSource)
16+
.Build(),
17+
DefaultBuilder()
18+
.AddReferences(typeof(Substitute))
19+
.AddSources(Source, IThing, AttributedFixtureSource)
20+
.Build(),
21+
];
22+
// lang=csharp
23+
private const string Source =
24+
"""
25+
namespace Goony.Goo.Goo;
26+
27+
public class LazyConstructor
28+
{
29+
public LazyConstructor(Lazy<IThing> lazyThing) { }
30+
}
31+
""";
32+
33+
// lang=csharp
34+
private const string AttributedFixtureSource =
35+
"""
36+
using Rocket.Surgery.Extensions.Testing.AutoFixtures;
37+
38+
namespace Goony.Goo.Goo.Tests;
39+
40+
[AutoFixture(typeof(LazyConstructor))]
41+
public class LazyConstructorFixture;
42+
""";
43+
44+
// lang=csharp
45+
private const string IThing =
46+
"""
47+
namespace Goony.Goo.Goo;
48+
49+
public interface IThing;
50+
""";
51+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
//HintName: Rocket.Surgery.Extensions.Testing.AutoFixtures/Rocket.Surgery.Extensions.Testing.AutoFixtures.AutoFixtureGenerator/LazyConstructor.AutoFixture.g.cs
2+
using System.Collections.ObjectModel;
3+
using FakeItEasy;
4+
using Goony.Goo.Goo;
5+
using Rocket.Surgery.Extensions.Testing.AutoFixtures;
6+
7+
namespace Goony.Goo.Goo.Tests
8+
{
9+
internal sealed partial class LazyConstructorFixture : AutoFixtureBase<LazyConstructorFixture>
10+
{
11+
public static implicit operator LazyConstructor(LazyConstructorFixture fixture) => fixture.Build();
12+
public LazyConstructorFixture WithLazyThing(Lazy<Goony.Goo.Goo.IThing> lazyThing) => With(ref _lazyThing, lazyThing);
13+
private LazyConstructor Build() => new LazyConstructor(_lazyThing);
14+
private Lazy<Goony.Goo.Goo.IThing> _lazyThing = default;
15+
}
16+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
{
2+
AnalyzerDiagnostics: {
3+
Rocket.Surgery.Extensions.Testing.AutoFixtures.Diagnostics.Rsaf0001: [],
4+
Rocket.Surgery.Extensions.Testing.AutoFixtures.Diagnostics.Rsaf0002: [],
5+
Rocket.Surgery.Extensions.Testing.AutoFixtures.Diagnostics.Rsaf0003: []
6+
},
7+
FinalDiagnostics: [],
8+
GeneratorDiagnostics: {
9+
Rocket.Surgery.Extensions.Testing.AutoFixtures.AutoFixtureGenerator: []
10+
},
11+
ParseOptions: {
12+
DocumentationMode: Parse
13+
},
14+
References: [
15+
FakeItEasy.dll,
16+
Microsoft.Extensions.Logging.Abstractions.dll,
17+
mscorlib.dll,
18+
netstandard.dll,
19+
System.Core.dll,
20+
System.dll,
21+
System.Private.CoreLib.dll,
22+
System.Runtime.dll
23+
]
24+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
//HintName: Rocket.Surgery.Extensions.Testing.AutoFixtures/Rocket.Surgery.Extensions.Testing.AutoFixtures.AutoFixtureGenerator/LazyConstructor.AutoFixture.g.cs
2+
using System.Collections.ObjectModel;
3+
using Goony.Goo.Goo;
4+
using NSubstitute;
5+
using Rocket.Surgery.Extensions.Testing.AutoFixtures;
6+
7+
namespace Goony.Goo.Goo.Tests
8+
{
9+
internal sealed partial class LazyConstructorFixture : AutoFixtureBase<LazyConstructorFixture>
10+
{
11+
public static implicit operator LazyConstructor(LazyConstructorFixture fixture) => fixture.Build();
12+
public LazyConstructorFixture WithLazyThing(Lazy<Goony.Goo.Goo.IThing> lazyThing) => With(ref _lazyThing, lazyThing);
13+
private LazyConstructor Build() => new LazyConstructor(_lazyThing);
14+
private Lazy<Goony.Goo.Goo.IThing> _lazyThing = default;
15+
}
16+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
{
2+
AnalyzerDiagnostics: {
3+
Rocket.Surgery.Extensions.Testing.AutoFixtures.Diagnostics.Rsaf0001: [],
4+
Rocket.Surgery.Extensions.Testing.AutoFixtures.Diagnostics.Rsaf0002: [],
5+
Rocket.Surgery.Extensions.Testing.AutoFixtures.Diagnostics.Rsaf0003: []
6+
},
7+
FinalDiagnostics: [],
8+
GeneratorDiagnostics: {
9+
Rocket.Surgery.Extensions.Testing.AutoFixtures.AutoFixtureGenerator: []
10+
},
11+
ParseOptions: {
12+
DocumentationMode: Parse
13+
},
14+
References: [
15+
Microsoft.Extensions.Logging.Abstractions.dll,
16+
mscorlib.dll,
17+
netstandard.dll,
18+
NSubstitute.dll,
19+
System.Core.dll,
20+
System.dll,
21+
System.Private.CoreLib.dll,
22+
System.Runtime.dll
23+
]
24+
}

test/Testing.AutoFixtures.Tests/snapshots/AutoFixtureGeneratorTests.GivenAutoFixture_WhenGenerate_ThenShouldGenerateAutoFixtureBase#AutoFixtureBase.g.verified.cs

Lines changed: 37 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ internal abstract class AutoFixtureBase<TFixture> : AutoFixtureBase
1818
/// <param name="field">The field.</param>
1919
/// <param name="value">The value.</param>
2020
/// <returns>The fixture.</returns>
21+
/// <exception cref="InvalidOperationException">Throws if it cannot cast the fixture.</exception>
2122
protected TFixture With<TField>(ref TField field, TField value)
2223
{
2324
field = value;
@@ -32,6 +33,7 @@ protected TFixture With<TField>(ref TField field, TField value)
3233
/// <param name="field">The field.</param>
3334
/// <param name="values">The values.</param>
3435
/// <returns>The fixture.</returns>
36+
/// <exception cref="InvalidOperationException">Throws if it cannot cast the fixture.</exception>
3537
protected TFixture With<TField>(ref Collection<TField>? field, IEnumerable<TField>? values)
3638
{
3739
if (values == null)
@@ -46,34 +48,36 @@ protected TFixture With<TField>(ref Collection<TField>? field, IEnumerable<TFiel
4648
}
4749

4850
/// <summary>
49-
/// Adds the specified list of fields to the fixture.
51+
/// Adds the specified field to the fixture.
5052
/// </summary>
5153
/// <typeparam name="TFixture">The type of the fixture.</typeparam>
5254
/// <typeparam name="TField">The type of the field.</typeparam>
5355
/// <param name="field">The field.</param>
54-
/// <param name="values">The values.</param>
56+
/// <param name="value">The value.</param>
5557
/// <returns>The fixture.</returns>
56-
protected TFixture With<TField>(ref List<TField>? field, IEnumerable<TField>? values)
58+
/// <exception cref="InvalidOperationException">Throws if it cannot cast the fixture.</exception>
59+
protected TFixture With<TField>(ref Collection<TField>? field, TField value)
5760
{
58-
if (values == null)
59-
field = null;
60-
else
61-
field?.AddRange(values);
62-
61+
field?.Add(value);
6362
return this as TFixture ?? throw new InvalidOperationException();
6463
}
6564

6665
/// <summary>
67-
/// Adds the specified field to the fixture.
66+
/// Adds the specified list of fields to the fixture.
6867
/// </summary>
6968
/// <typeparam name="TFixture">The type of the fixture.</typeparam>
7069
/// <typeparam name="TField">The type of the field.</typeparam>
7170
/// <param name="field">The field.</param>
72-
/// <param name="value">The value.</param>
71+
/// <param name="values">The values.</param>
7372
/// <returns>The fixture.</returns>
74-
protected TFixture With<TField>(ref Collection<TField>? field, TField value)
73+
/// <exception cref="InvalidOperationException">Throws if it cannot cast the fixture.</exception>
74+
protected TFixture With<TField>(ref List<TField>? field, IEnumerable<TField>? values)
7575
{
76-
field?.Add(value);
76+
if (values == null)
77+
field = null;
78+
else
79+
field?.AddRange(values);
80+
7781
return this as TFixture ?? throw new InvalidOperationException();
7882
}
7983

@@ -85,6 +89,7 @@ protected TFixture With<TField>(ref Collection<TField>? field, TField value)
8589
/// <param name="field">The field.</param>
8690
/// <param name="value">The value.</param>
8791
/// <returns>The fixture.</returns>
92+
/// <exception cref="InvalidOperationException">Throws if it cannot cast the fixture.</exception>
8893
protected TFixture With<TField>(ref List<TField>? field, TField value)
8994
{
9095
field?.Add(value);
@@ -100,6 +105,7 @@ protected TFixture With<TField>(ref List<TField>? field, TField value)
100105
/// <param name="dictionary">The dictionary.</param>
101106
/// <param name="keyValuePair">The key value pair.</param>
102107
/// <returns>The fixture.</returns>
108+
/// <exception cref="InvalidOperationException">Throws if it cannot cast the fixture.</exception>
103109
protected TFixture With<TKey, TField>(
104110
ref Dictionary<TKey, TField> dictionary,
105111
KeyValuePair<TKey, TField> keyValuePair
@@ -122,6 +128,7 @@ KeyValuePair<TKey, TField> keyValuePair
122128
/// <param name="key">The key.</param>
123129
/// <param name="value">The value.</param>
124130
/// <returns>The fixture.</returns>
131+
/// <exception cref="InvalidOperationException">Throws if it cannot cast the fixture.</exception>
125132
protected TFixture With<TKey, TField>(ref Dictionary<TKey, TField> dictionary, TKey key, TField value)
126133
where TKey : notnull
127134
{
@@ -140,6 +147,7 @@ protected TFixture With<TKey, TField>(ref Dictionary<TKey, TField> dictionary, T
140147
/// <param name="dictionary">The dictionary.</param>
141148
/// <param name="keyValuePair">The key value pair.</param>
142149
/// <returns>The fixture.</returns>
150+
/// <exception cref="InvalidOperationException">Throws if it cannot cast the fixture.</exception>
143151
protected TFixture With<TKey, TField>(
144152
ref Dictionary<TKey, TField> dictionary,
145153
Dictionary<TKey, TField> keyValuePair
@@ -149,5 +157,21 @@ Dictionary<TKey, TField> keyValuePair
149157
dictionary = keyValuePair;
150158
return this as TFixture ?? throw new InvalidOperationException();
151159
}
160+
161+
/// <summary>
162+
/// Adds the specified lazy field to the fixture.
163+
/// </summary>
164+
/// <param name="field">The field.</param>
165+
/// <param name="value">The value.</param>
166+
/// <typeparam name="TFixture">The type of the fixture.</typeparam>
167+
/// <typeparam name="TField">The type of the field.</typeparam>
168+
/// <returns></returns>
169+
/// <returns>The fixture.</returns>
170+
/// <exception cref="InvalidOperationException">Throws if it cannot cast the fixture.</exception>
171+
protected TFixture With<TField>(ref Lazy<TField> field, TField value)
172+
{
173+
field = new(() => value);
174+
return this as TFixture ?? throw new InvalidOperationException();
175+
}
152176
}
153-
}
177+
}

0 commit comments

Comments
 (0)