Skip to content

Commit 89164f0

Browse files
committed
Added alternative idea for the constructor factories so that the use of the factories is more explicit
1 parent 72280f3 commit 89164f0

File tree

7 files changed

+85
-36
lines changed

7 files changed

+85
-36
lines changed

TestStack.Dossier.Tests/Builders/AutoConstructorCustomerBuilder.cs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,6 @@ namespace TestStack.Dossier.Tests.Builders
55
{
66
class AutoConstructorCustomerBuilder : TestDataBuilder<Customer, AutoConstructorCustomerBuilder>
77
{
8-
public AutoConstructorCustomerBuilder()
9-
: base(new ConstructorFactory()) { }
10-
118
public AutoConstructorCustomerBuilder WithFirstName(string firstName)
129
{
1310
return Set(x => x.FirstName, firstName);
@@ -22,5 +19,10 @@ public AutoConstructorCustomerBuilder WhoJoinedIn(int year)
2219
{
2320
return Set(x => x.YearJoined, year);
2421
}
22+
23+
protected override Customer BuildObject()
24+
{
25+
return BuildUsing<ConstructorFactory>();
26+
}
2527
}
2628
}

TestStack.Dossier.Tests/Builders/StudentViewModelBuilder.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System;
2+
using TestStack.Dossier.Factories;
23
using TestStack.Dossier.Tests.Stubs.ViewModels;
34

45
namespace TestStack.Dossier.Tests.Builders
@@ -19,5 +20,10 @@ public virtual StudentViewModelBuilder WhoEntrolledIn(DateTime enrollmentDate)
1920
{
2021
return Set(x => x.EnrollmentDate, enrollmentDate);
2122
}
23+
24+
protected override StudentViewModel BuildObject()
25+
{
26+
return BuildUsing<AllPropertiesFactory>();
27+
}
2228
}
2329
}

TestStack.Dossier.Tests/TestStack.Dossier.Tests.csproj

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -98,12 +98,6 @@
9898
<SubType>Designer</SubType>
9999
</None>
100100
</ItemGroup>
101-
<ItemGroup>
102-
<ProjectReference Include="..\TestStack.Dossier\TestStack.Dossier.csproj">
103-
<Project>{01e4ee61-ab1a-4177-8b6c-d50205d167a9}</Project>
104-
<Name>TestStack.Dossier</Name>
105-
</ProjectReference>
106-
</ItemGroup>
107101
<ItemGroup>
108102
<Content Include="SampleDictionaryFile.txt">
109103
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
@@ -112,6 +106,12 @@
112106
<ItemGroup>
113107
<Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
114108
</ItemGroup>
109+
<ItemGroup>
110+
<ProjectReference Include="..\TestStack.Dossier\TestStack.Dossier.csproj">
111+
<Project>{01e4ee61-ab1a-4177-8b6c-d50205d167a9}</Project>
112+
<Name>TestStack.Dossier</Name>
113+
</ProjectReference>
114+
</ItemGroup>
115115
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
116116
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
117117
Other similar extension points exist, see Microsoft.Common.targets.

TestStack.Dossier/AnonymousValueFixture.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,12 @@ public T Get<TObject, T>(Expression<Func<TObject, T>> property)
9191
return valueSupplier.GenerateAnonymousValue<TObject, T>(this, propertyName);
9292
}
9393

94+
/// <summary>
95+
/// Automatically generate an anonymous value for the given property expression.
96+
/// </summary>
97+
/// <param name="type">The type of the property</param>
98+
/// <param name="propertyName">The name of the property</param>
99+
/// <returns>The anonymous value, taking into account any registered conventions</returns>
94100
public object Get(Type type, string propertyName)
95101
{
96102
var valueSupplier = LocalValueSuppliers

TestStack.Dossier/Builder.cs

Lines changed: 48 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,67 @@
1-
using TestStack.Dossier.Factories;
1+
using Ploeh.AutoFixture.Kernel;
2+
using TestStack.Dossier.Factories;
3+
using TestStack.Dossier.Lists;
24

35
namespace TestStack.Dossier
46
{
57
/// <summary>
6-
/// A stand-alone class for building objects on the fly.
8+
/// A generic Test Data Builder implementation for building objects on the fly.
9+
/// By default
710
/// </summary>
811
/// <typeparam name="T">The type of object this class generates.</typeparam>
912
public class Builder<T> : TestDataBuilder<T, Builder<T>>
1013
where T : class
1114
{
15+
/// <summary>
16+
/// Default constructor.
17+
/// </summary>
18+
public Builder()
19+
{
20+
Factory = new AllPropertiesFactory();
21+
}
22+
23+
private IFactory Factory { get; set; }
24+
25+
internal Builder<T> SetFactory(IFactory factory)
26+
{
27+
Factory = factory;
28+
return this;
29+
}
30+
1231
/// <summary>
1332
/// Initialises a new Builder.
1433
/// </summary>
34+
/// <param name="factory">The type of factory to use to construct the object, uses <see cref="AllPropertiesFactory"/> by default</param>
1535
/// <returns>Returns a new instance of a Builder for the type of T</returns>
1636
public static Builder<T> CreateNew(IFactory factory = null)
1737
{
18-
if (factory == null)
38+
return new Builder<T>
1939
{
20-
factory = new AllPropertiesFactory();
21-
}
22-
return new Builder<T> {Factory = factory};
40+
Factory = factory ?? new AllPropertiesFactory()
41+
};
42+
}
43+
44+
/// <summary>
45+
/// Creates an list builder expression that allows you to create a list of entities.
46+
/// You can call .First(x), .Last(x), etc. methods followed by chained builder method calls.
47+
/// When you are done call .BuildList() to get the list of entities.
48+
/// This override allows you to specify the factory that is used to construct the objects,
49+
/// the default implementation uses the <see cref="AllPropertiesFactory"/>.
50+
/// </summary>
51+
/// <param name="size">The size of list</param>
52+
/// <param name="factory">The factory to use to construct the object</param>
53+
/// <returns>The list builder for a list of {TBuilder} of the specified size</returns>
54+
public static ListBuilder<T, Builder<T>> CreateListOfSize(int size, IFactory factory)
55+
{
56+
var lb = new ListBuilder<T, Builder<T>>(size);
57+
lb.All().With(b => b.SetFactory(factory));
58+
return lb;
2359
}
60+
61+
/// <inheritdoc />
62+
protected override T BuildObject()
63+
{
64+
return Factory.BuildObject(this);
65+
}
2466
}
2567
}

TestStack.Dossier/Lists/EnsureAllMethodsVirtual.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ public void MethodsInspected()
1313

1414
public void NonProxyableMemberNotification(Type type, MemberInfo memberInfo)
1515
{
16-
if (new[]{"get_Any", "set_Any", "Build", "AsProxy", "Get", "GetOrDefault", "Set", "Has", "get_ListBuilder", "set_ListBuilder"}.Contains(memberInfo.Name))
16+
if (new[]{"get_Any", "set_Any", "Build", "AsProxy", "Get", "GetOrDefault", "Set", "Has", "get_ListBuilder", "set_ListBuilder", "BuildUsing", "SetFactory"}.Contains(memberInfo.Name))
1717
return;
1818
throw new InvalidOperationException(string.Format("Tried to build a list with a builder who has non-virtual method. Please make {0} on type {1} virtual.", memberInfo.Name, type.Name));
1919
}

TestStack.Dossier/TestDataBuilder.cs

Lines changed: 13 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -19,29 +19,15 @@ public abstract class TestDataBuilder<TObject, TBuilder>
1919
private ProxyBuilder<TObject> _proxyBuilder;
2020

2121
/// <summary>
22-
/// The factory used to create the instance of TObject.
23-
/// </summary>
24-
public IFactory Factory;
25-
26-
/// <summary>
27-
/// The list builder instance (if this ia a list builder proxy).
22+
/// The list builder instance (if this is a a list builder proxy).
2823
/// </summary>
2924
public ListBuilder<TObject, TBuilder> ListBuilder { get; internal set; }
3025

3126
/// <summary>
3227
/// Default Constructor.
3328
/// </summary>
3429
protected TestDataBuilder()
35-
: this(new AllPropertiesFactory())
36-
{
37-
}
38-
39-
/// <summary>
40-
/// Allow object builder factory to be passed in
41-
/// </summary>
42-
protected TestDataBuilder(IFactory factory)
4330
{
44-
Factory = factory;
4531
Any = new AnonymousValueFixture();
4632
}
4733

@@ -85,14 +71,21 @@ public static implicit operator List<TObject>(TestDataBuilder<TObject, TBuilder>
8571
}
8672

8773
/// <summary>
88-
/// Build the actual object - you can optionally override this and call the constructor and any other methods.
74+
/// Build the actual object - you can call the <see cref="BuildUsing{TFactory}"/> method to quickly build a builder.
8975
/// </summary>
9076
/// <returns>The built object</returns>
91-
protected virtual TObject BuildObject()
77+
protected abstract TObject BuildObject();
78+
79+
/// <summary>
80+
///
81+
/// </summary>
82+
/// <typeparam name="TFactory"></typeparam>
83+
/// <returns></returns>
84+
protected TObject BuildUsing<TFactory>()
85+
where TFactory : IFactory, new()
9286
{
93-
var model = Factory.BuildObject(this);
94-
95-
return model;
87+
var factory = new TFactory();
88+
return factory.BuildObject(this);
9689
}
9790

9891
/// <summary>

0 commit comments

Comments
 (0)