From 205c61ecfd086b518751cc96e8e079d32fb6deba Mon Sep 17 00:00:00 2001 From: Michael Whelan Date: Sun, 26 Apr 2015 10:19:48 +0100 Subject: [PATCH 01/13] Added a static Builder class to emulate NBuilder behaviour --- .../BuilderBuildListTests.cs | 194 ++++++++++++++++++ TestStack.Dossier.Tests/BuilderBuildTests.cs | 56 +++++ TestStack.Dossier.Tests/GetAnonymousTests.cs | 14 +- .../StaticAnonymousValueSupplier.cs | 14 +- .../TestStack.Dossier.Tests.csproj | 2 + TestStack.Dossier/AnonymousValueFixture.cs | 10 + TestStack.Dossier/Builder.cs | 13 ++ TestStack.Dossier/IAnonymousValueSupplier.cs | 22 +- TestStack.Dossier/PropertyNameGetter.cs | 26 +++ .../Suppliers/DefaultEmailValueSupplier.cs | 17 +- .../DefaultFirstNameValueSupplier.cs | 17 +- .../Suppliers/DefaultLastNameValueSupplier.cs | 18 +- .../Suppliers/DefaultStringValueSupplier.cs | 15 +- .../Suppliers/DefaultValueSupplier.cs | 21 +- .../DefaultValueTypeValueSupplier.cs | 21 +- TestStack.Dossier/TestDataBuilder.cs | 38 +++- TestStack.Dossier/TestStack.Dossier.csproj | 1 + 17 files changed, 483 insertions(+), 16 deletions(-) create mode 100644 TestStack.Dossier.Tests/BuilderBuildListTests.cs create mode 100644 TestStack.Dossier.Tests/BuilderBuildTests.cs create mode 100644 TestStack.Dossier/Builder.cs diff --git a/TestStack.Dossier.Tests/BuilderBuildListTests.cs b/TestStack.Dossier.Tests/BuilderBuildListTests.cs new file mode 100644 index 0000000..658815e --- /dev/null +++ b/TestStack.Dossier.Tests/BuilderBuildListTests.cs @@ -0,0 +1,194 @@ +using System.Collections.Generic; +using System.Linq; +using Shouldly; +using TestStack.Dossier.DataSources.Generators; +using TestStack.Dossier.Lists; +using TestStack.Dossier.Tests.Builders; +using TestStack.Dossier.Tests.Entities; +using Xunit; + +namespace TestStack.Dossier.Tests +{ + public class BuilderBuildListTests + { + [Fact] + public void GivenANormalBuilderInstance_WhenCallingIsListBuilderProxy_ThenReturnFalse() + { + var builder = Builder.CreateNew(); + + builder.IsListBuilderProxy().ShouldBe(false); + } + + [Fact] + public void GivenAListBuilderProxyInstance_WhenCallingIsListBuilderProxy_ThenReturnTrue() + { + var builder = Builder.CreateListOfSize(1).TheFirst(1); + + builder.IsListBuilderProxy().ShouldBe(true); + } + + [Fact] + public void GivenListOfBuilders_WhenCallingBuildListExplicitly_ThenAListOfEntitiesOfTheRightSizeShouldBeReturned() + { + var builders = Builder.CreateListOfSize(5); + + var entities = builders.BuildList(); + + entities.Count.ShouldBe(5); + } + + [Fact] + public void GivenListOfBuilders_WhenCallingBuildListImplicitly_ThenAListOfEntitiesOfTheRightSizeShouldBeReturned() + { + List entities = Builder.CreateListOfSize(5); + + entities.Count.ShouldBe(5); + } + + [Fact] + public void GivenListOfBuilders_WhenCallingBuildListExplicitly_ThenAListOfEntitiesOfTheRightTypeShouldBeReturned() + { + var builders = Builder.CreateListOfSize(5); + + var entities = builders.BuildList(); + + entities.ShouldBeAssignableTo>(); + } + + [Fact] + public void GivenListOfBuilders_WhenCallingBuildListImplicitly_ThenAListOfEntitiesOfTheRightTypeShouldBeReturned() + { + List entities = Builder.CreateListOfSize(5); + + entities.ShouldBeAssignableTo>(); + } + + [Fact] + public void GivenListOfBuilders_WhenCallingBuildListExplicitly_ThenAListOfUniqueEntitiesShouldBeReturned() + { + var builders = Builder.CreateListOfSize(5); + + var entities = builders.BuildList(); + + entities[0].ShouldNotBe(entities[1]); + entities[0].ShouldNotBe(entities[2]); + entities[0].ShouldNotBe(entities[3]); + entities[0].ShouldNotBe(entities[4]); + entities[1].ShouldNotBe(entities[2]); + entities[1].ShouldNotBe(entities[3]); + entities[1].ShouldNotBe(entities[4]); + entities[2].ShouldNotBe(entities[3]); + entities[2].ShouldNotBe(entities[4]); + entities[3].ShouldNotBe(entities[4]); + } + + [Fact] + public void GivenListOfBuilders_WhenCallingBuildListImplicitly_ThenAListOfUniqueEntitiesShouldBeReturned() + { + List entities = Builder.CreateListOfSize(5); + + entities[0].ShouldNotBe(entities[1]); + entities[0].ShouldNotBe(entities[2]); + entities[0].ShouldNotBe(entities[3]); + entities[0].ShouldNotBe(entities[4]); + entities[1].ShouldNotBe(entities[2]); + entities[1].ShouldNotBe(entities[3]); + entities[1].ShouldNotBe(entities[4]); + entities[2].ShouldNotBe(entities[3]); + entities[2].ShouldNotBe(entities[4]); + entities[3].ShouldNotBe(entities[4]); + } + + [Fact] + public void GivenListOfBuildersWithCustomisation_WhenBuildingEntitiesExplicitly_ThenTheCustomisationShouldTakeEffect() + { + var generator = new SequentialGenerator(0, 100); + var list = CustomerBuilder.CreateListOfSize(3) + .All().With(b => b.WithFirstName(generator.Generate().ToString())); + + var data = list.BuildList(); + + data.Select(c => c.FirstName).ToArray() + .ShouldBe(new[] { "0", "1", "2" }); + } + + [Fact] + public void GivenListOfBuildersWithCustomisation_WhenBuildingEntitiesImplicitly_ThenTheCustomisationShouldTakeEffect() + { + var generator = new SequentialGenerator(0, 100); + + List data = CustomerBuilder.CreateListOfSize(3) + .All().With(b => b.WithFirstName(generator.Generate().ToString())); + + data.Select(c => c.FirstName).ToArray() + .ShouldBe(new[] { "0", "1", "2" }); + } + + [Fact] + public void GivenListOfBuildersWithARangeOfCustomisationMethods_WhenBuildingEntitiesExplicitly_ThenThenTheListIsBuiltAndModifiedCorrectly() + { + var i = 0; + var customers = CustomerBuilder.CreateListOfSize(5) + .TheFirst(1).WithFirstName("First") + .TheNext(1).WithLastName("Next Last") + .TheLast(1).WithLastName("Last Last") + .ThePrevious(2).With(b => b.WithLastName("last" + (++i).ToString())) + .All().WhoJoinedIn(1999) + .BuildList(); + + customers.ShouldBeAssignableTo>(); + customers.Count.ShouldBe(5); + customers[0].FirstName.ShouldBe("First"); + customers[1].LastName.ShouldBe("Next Last"); + customers[2].LastName.ShouldBe("last1"); + customers[3].LastName.ShouldBe("last2"); + customers[4].LastName.ShouldBe("Last Last"); + customers.ShouldAllBe(c => c.YearJoined == 1999); + } + + [Fact] + public void GivenListOfBuildersWithARangeOfCustomisationMethods_WhenBuildingEntitiesImplicitly_ThenThenTheListIsBuiltAndModifiedCorrectly() + { + var i = 0; + List customers = CustomerBuilder.CreateListOfSize(5) + .TheFirst(1).WithFirstName("First") + .TheNext(1).WithLastName("Next Last") + .TheLast(1).WithLastName("Last Last") + .ThePrevious(2).With(b => b.WithLastName("last" + (++i).ToString())) + .All().WhoJoinedIn(1999); + + customers.ShouldBeAssignableTo>(); + customers.Count.ShouldBe(5); + customers[0].FirstName.ShouldBe("First"); + customers[1].LastName.ShouldBe("Next Last"); + customers[2].LastName.ShouldBe("last1"); + customers[3].LastName.ShouldBe("last2"); + customers[4].LastName.ShouldBe("Last Last"); + customers.ShouldAllBe(c => c.YearJoined == 1999); + } + + [Fact] + public void WhenBuildingEntitiesExplicitly_ThenTheAnonymousValueFixtureIsSharedAcrossBuilders() + { + var customers = CustomerBuilder.CreateListOfSize(5).BuildList(); + + customers[0].CustomerClass.ShouldBe(CustomerClass.Normal); + customers[1].CustomerClass.ShouldBe(CustomerClass.Bronze); + customers[2].CustomerClass.ShouldBe(CustomerClass.Silver); + customers[3].CustomerClass.ShouldBe(CustomerClass.Gold); + customers[4].CustomerClass.ShouldBe(CustomerClass.Platinum); + } + + [Fact] + public void WhenBuildingEntitiesImplicitly_ThenTheAnonymousValueFixtureIsSharedAcrossBuilders() + { + List customers = CustomerBuilder.CreateListOfSize(5); + + customers[0].CustomerClass.ShouldBe(CustomerClass.Normal); + customers[1].CustomerClass.ShouldBe(CustomerClass.Bronze); + customers[2].CustomerClass.ShouldBe(CustomerClass.Silver); + customers[3].CustomerClass.ShouldBe(CustomerClass.Gold); + customers[4].CustomerClass.ShouldBe(CustomerClass.Platinum); + } + } +} \ No newline at end of file diff --git a/TestStack.Dossier.Tests/BuilderBuildTests.cs b/TestStack.Dossier.Tests/BuilderBuildTests.cs new file mode 100644 index 0000000..6b38f91 --- /dev/null +++ b/TestStack.Dossier.Tests/BuilderBuildTests.cs @@ -0,0 +1,56 @@ +using Shouldly; +using TestStack.Dossier.Tests.Builders; +using TestStack.Dossier.Tests.Entities; +using Xunit; + +namespace TestStack.Dossier.Tests +{ + public class BuilderBuildTests + { + [Fact] + public void GivenBasicBuilder_WhenCallingBuildExplicitly_ThenReturnAnObject() + { + var builder = Builder.CreateNew(); + + var customer = builder.Build(); + + customer.ShouldBeOfType(); + } + + [Fact] + public void GivenBuilder_WhenCallingSetExplicitly_ShouldOverrideValues() + { + var builder = Builder.CreateNew() + .Set(x => x.FirstName, "Pi") + .Set(x => x.LastName, "Lanningham") + .Set(x => x.YearJoined, 2014); + + var customer = builder.Build(); + + customer.FirstName.ShouldBe("Pi"); + customer.LastName.ShouldBe("Lanningham"); + customer.YearJoined.ShouldBe(2014); + } + + [Fact] + public void GivenBasicBuilder_WhenCallingBuildImplicitly_ThenReturnAnObject() + { + Customer customer = Builder.CreateNew(); + + customer.ShouldBeOfType(); + } + + [Fact] + public void GivenBuilder_WhenCallingSetImplicitly_ShouldOverrideValues() + { + Customer customer = Builder.CreateNew() + .Set(x => x.FirstName, "Pi") + .Set(x => x.LastName, "Lanningham") + .Set(x => x.YearJoined, 2014); + + customer.FirstName.ShouldBe("Pi"); + customer.LastName.ShouldBe("Lanningham"); + customer.YearJoined.ShouldBe(2014); + } + } +} \ No newline at end of file diff --git a/TestStack.Dossier.Tests/GetAnonymousTests.cs b/TestStack.Dossier.Tests/GetAnonymousTests.cs index 442b556..c415c73 100644 --- a/TestStack.Dossier.Tests/GetAnonymousTests.cs +++ b/TestStack.Dossier.Tests/GetAnonymousTests.cs @@ -1,4 +1,5 @@ -using Shouldly; +using System; +using Shouldly; using TestStack.Dossier.DataSources.Person; using TestStack.Dossier.Lists; using TestStack.Dossier.Tests.Builders; @@ -113,9 +114,20 @@ public bool CanSupplyValue(string propertyName) && propertyName.ToLower().StartsWith("year"); } + public bool CanSupplyValue(Type type, string propertyName) + { + return type == typeof(int) + && propertyName.ToLower().StartsWith("year"); + } + public TValue GenerateAnonymousValue(AnonymousValueFixture any, string propertyName) { return (TValue)(object)_year++; } + + public object GenerateAnonymousValue(AnonymousValueFixture any, Type type, string propertyName) + { + return _year++; + } } } diff --git a/TestStack.Dossier.Tests/TestHelpers/StaticAnonymousValueSupplier.cs b/TestStack.Dossier.Tests/TestHelpers/StaticAnonymousValueSupplier.cs index dc3db91..4c7c9a0 100644 --- a/TestStack.Dossier.Tests/TestHelpers/StaticAnonymousValueSupplier.cs +++ b/TestStack.Dossier.Tests/TestHelpers/StaticAnonymousValueSupplier.cs @@ -1,4 +1,6 @@ -namespace TestStack.Dossier.Tests.TestHelpers +using System; + +namespace TestStack.Dossier.Tests.TestHelpers { public class StaticAnonymousValueSupplier : IAnonymousValueSupplier { @@ -14,9 +16,19 @@ public bool CanSupplyValue(string propertyName) return typeof(TValue) == _valueToSupply.GetType(); } + public bool CanSupplyValue(Type type, string propertyName) + { + return type == _valueToSupply.GetType(); + } + public TValue GenerateAnonymousValue(AnonymousValueFixture any, string propertyName) { return (TValue) _valueToSupply; } + + public object GenerateAnonymousValue(AnonymousValueFixture any, Type type, string propertyName) + { + return _valueToSupply; + } } } diff --git a/TestStack.Dossier.Tests/TestStack.Dossier.Tests.csproj b/TestStack.Dossier.Tests/TestStack.Dossier.Tests.csproj index 73d099b..0b2c2b0 100644 --- a/TestStack.Dossier.Tests/TestStack.Dossier.Tests.csproj +++ b/TestStack.Dossier.Tests/TestStack.Dossier.Tests.csproj @@ -54,6 +54,8 @@ + + diff --git a/TestStack.Dossier/AnonymousValueFixture.cs b/TestStack.Dossier/AnonymousValueFixture.cs index 64e193e..fc0311d 100644 --- a/TestStack.Dossier/AnonymousValueFixture.cs +++ b/TestStack.Dossier/AnonymousValueFixture.cs @@ -90,5 +90,15 @@ public T Get(Expression> property) return valueSupplier.GenerateAnonymousValue(this, propertyName); } + + public object Get(Type type, string propertyName) + { + var valueSupplier = LocalValueSuppliers + .Concat(GlobalValueSuppliers) + .Concat(DefaultValueSuppliers) + .First(s => s.CanSupplyValue(type,propertyName)); + + return valueSupplier.GenerateAnonymousValue(this, type, propertyName); + } } } diff --git a/TestStack.Dossier/Builder.cs b/TestStack.Dossier/Builder.cs new file mode 100644 index 0000000..ca9fd3b --- /dev/null +++ b/TestStack.Dossier/Builder.cs @@ -0,0 +1,13 @@ +using System; + +namespace TestStack.Dossier +{ + public class Builder : TestDataBuilder> + where T : class + { + public static Builder CreateNew() + { + return new Builder(); + } + } +} diff --git a/TestStack.Dossier/IAnonymousValueSupplier.cs b/TestStack.Dossier/IAnonymousValueSupplier.cs index eae1839..9ead160 100644 --- a/TestStack.Dossier/IAnonymousValueSupplier.cs +++ b/TestStack.Dossier/IAnonymousValueSupplier.cs @@ -1,4 +1,6 @@ -namespace TestStack.Dossier +using System; + +namespace TestStack.Dossier { /// /// Inheritors can supply an anonymous value. @@ -14,6 +16,14 @@ public interface IAnonymousValueSupplier /// Whether or not this supplier can supply an anonymous value bool CanSupplyValue(string propertyName); + /// + /// Returns whether or not this supplier can supply an anonymous value for the given property. + /// + /// The type of the property to generate a value for + /// The name of the property to generate a value for + /// Whether or not this supplier can supply an anonymous value + bool CanSupplyValue(Type type, string propertyName); + /// /// Return an anonymous value for the given property and fixture. /// @@ -23,5 +33,15 @@ public interface IAnonymousValueSupplier /// The name of the property to return an anonymous value for /// The anonymous value TValue GenerateAnonymousValue(AnonymousValueFixture any, string propertyName); + + /// + /// Return an anonymous value for the given property and fixture. + /// + /// The type that the property is enclosed in + /// The type of the target property - the required anonymous value is of this type + /// Anonymous value fixture + /// The name of the property to return an anonymous value for + /// The anonymous value + object GenerateAnonymousValue(AnonymousValueFixture any, Type type, string propertyName); } } diff --git a/TestStack.Dossier/PropertyNameGetter.cs b/TestStack.Dossier/PropertyNameGetter.cs index 2270e16..df0de58 100644 --- a/TestStack.Dossier/PropertyNameGetter.cs +++ b/TestStack.Dossier/PropertyNameGetter.cs @@ -1,5 +1,7 @@ using System; +using System.Linq; using System.Linq.Expressions; +using System.Reflection; namespace TestStack.Dossier { @@ -20,5 +22,29 @@ public static string Get(Expression> prop return memExp.Member.Name; } + + public static ConstructorInfo GetConstructor(Type type) + { + if (type == null) + throw new ArgumentNullException("type"); + + var ctors = type.GetConstructors() + .OrderByDescending(x => x.GetParameters().Length) + .ToArray(); + + if (ctors.Length == 0) + throw new InvalidOperationException(string.Format("The given type {0} does not contain any public constructors.", type.Name)); + + if (ctors.Length > 1 && ctors[0].GetParameters().Length == ctors[1].GetParameters().Length) + throw new InvalidOperationException(string.Format("Can't select best suited constructor between {0} and {1}.", GetConstructorSignature(ctors[0]), GetConstructorSignature(ctors[1]))); + + return ctors[0]; + } + + public static string GetConstructorSignature(ConstructorInfo ctor) + { + var typeName = ctor.DeclaringType == null ? "" : ctor.DeclaringType.Name; + return typeName + ctor.ToString().Substring("Void ".Length); + } } } diff --git a/TestStack.Dossier/Suppliers/DefaultEmailValueSupplier.cs b/TestStack.Dossier/Suppliers/DefaultEmailValueSupplier.cs index 2ea3b4a..9c1cd55 100644 --- a/TestStack.Dossier/Suppliers/DefaultEmailValueSupplier.cs +++ b/TestStack.Dossier/Suppliers/DefaultEmailValueSupplier.cs @@ -1,4 +1,5 @@ -using TestStack.Dossier.EquivalenceClasses.Person; +using System; +using TestStack.Dossier.EquivalenceClasses.Person; namespace TestStack.Dossier.Suppliers { @@ -10,7 +11,13 @@ public class DefaultEmailValueSupplier : IAnonymousValueSupplier /// public bool CanSupplyValue(string propertyName) { - return typeof (TValue) == typeof(string) && propertyName.ToLower().Contains("email"); + return CanSupplyValue(typeof(string), propertyName); + } + + /// + public bool CanSupplyValue(Type type, string propertyName) + { + return type == typeof(string) && propertyName.ToLower().Contains("email"); } /// @@ -18,5 +25,11 @@ public TValue GenerateAnonymousValue(AnonymousValueFixture any, { return (TValue) (object) any.EmailAddress(); } + + /// + public object GenerateAnonymousValue(AnonymousValueFixture any, Type type, string propertyName) + { + return any.EmailAddress(); + } } } diff --git a/TestStack.Dossier/Suppliers/DefaultFirstNameValueSupplier.cs b/TestStack.Dossier/Suppliers/DefaultFirstNameValueSupplier.cs index 10251ca..2ab4fe8 100644 --- a/TestStack.Dossier/Suppliers/DefaultFirstNameValueSupplier.cs +++ b/TestStack.Dossier/Suppliers/DefaultFirstNameValueSupplier.cs @@ -1,4 +1,5 @@ -using TestStack.Dossier.EquivalenceClasses.Person; +using System; +using TestStack.Dossier.EquivalenceClasses.Person; namespace TestStack.Dossier.Suppliers { @@ -10,7 +11,13 @@ public class DefaultFirstNameValueSupplier : IAnonymousValueSupplier /// public bool CanSupplyValue(string propertyName) { - return typeof (TValue) == typeof(string) && propertyName.ToLower() == "firstname"; + return CanSupplyValue(typeof (TValue), propertyName); + } + + /// + public bool CanSupplyValue(Type type, string propertyName) + { + return type == typeof(string) && propertyName.ToLower() == "firstname"; } /// @@ -18,5 +25,11 @@ public TValue GenerateAnonymousValue(AnonymousValueFixture any, { return (TValue) (object) any.FirstName(); } + + /// + public object GenerateAnonymousValue(AnonymousValueFixture any, Type type, string propertyName) + { + return any.FirstName(); + } } } diff --git a/TestStack.Dossier/Suppliers/DefaultLastNameValueSupplier.cs b/TestStack.Dossier/Suppliers/DefaultLastNameValueSupplier.cs index 522bd4e..d188e23 100644 --- a/TestStack.Dossier/Suppliers/DefaultLastNameValueSupplier.cs +++ b/TestStack.Dossier/Suppliers/DefaultLastNameValueSupplier.cs @@ -1,4 +1,5 @@ -using TestStack.Dossier.EquivalenceClasses.Person; +using System; +using TestStack.Dossier.EquivalenceClasses.Person; namespace TestStack.Dossier.Suppliers { @@ -14,10 +15,23 @@ public bool CanSupplyValue(string propertyName) (propertyName.ToLower() == "lastname" || propertyName.ToLower() == "surname"); } + /// + public bool CanSupplyValue(Type type, string propertyName) + { + return type == typeof(string) && + (propertyName.ToLower() == "lastname" || propertyName.ToLower() == "surname"); + } + /// public TValue GenerateAnonymousValue(AnonymousValueFixture any, string propertyName) { - return (TValue) (object) any.LastName(); + return (TValue)(object)any.LastName(); + } + + /// + public object GenerateAnonymousValue(AnonymousValueFixture any, Type type, string propertyName) + { + return any.LastName(); } } } diff --git a/TestStack.Dossier/Suppliers/DefaultStringValueSupplier.cs b/TestStack.Dossier/Suppliers/DefaultStringValueSupplier.cs index f63b4a3..0381230 100644 --- a/TestStack.Dossier/Suppliers/DefaultStringValueSupplier.cs +++ b/TestStack.Dossier/Suppliers/DefaultStringValueSupplier.cs @@ -1,4 +1,5 @@ -using TestStack.Dossier.EquivalenceClasses; +using System; +using TestStack.Dossier.EquivalenceClasses; namespace TestStack.Dossier.Suppliers { @@ -13,10 +14,22 @@ public bool CanSupplyValue(string propertyName) return typeof (TValue) == typeof(string); } + /// + public bool CanSupplyValue(Type type, string propertyName) + { + return type == typeof(string); + } + /// public TValue GenerateAnonymousValue(AnonymousValueFixture any, string propertyName) { return (TValue) (object) any.StringStartingWith(propertyName); } + + /// + public object GenerateAnonymousValue(AnonymousValueFixture any, Type type, string propertyName) + { + return any.StringStartingWith(propertyName); + } } } diff --git a/TestStack.Dossier/Suppliers/DefaultValueSupplier.cs b/TestStack.Dossier/Suppliers/DefaultValueSupplier.cs index bd1ed89..775c699 100644 --- a/TestStack.Dossier/Suppliers/DefaultValueSupplier.cs +++ b/TestStack.Dossier/Suppliers/DefaultValueSupplier.cs @@ -1,4 +1,6 @@ -namespace TestStack.Dossier.Suppliers +using System; + +namespace TestStack.Dossier.Suppliers { /// /// Supplies default value for any type. @@ -11,10 +13,27 @@ public bool CanSupplyValue(string propertyName) return true; } + /// + public bool CanSupplyValue(Type type, string propertyName) + { + return true; + } + /// public TValue GenerateAnonymousValue(AnonymousValueFixture any, string propertyName) { return default(TValue); } + + /// + public object GenerateAnonymousValue(AnonymousValueFixture any, Type type, string propertyName) + { + // See stackoverflow: http://stackoverflow.com/questions/325426/programmatic-equivalent-of-defaulttype + if (type.IsValueType) + { + return Activator.CreateInstance(type); + } + return null; + } } } diff --git a/TestStack.Dossier/Suppliers/DefaultValueTypeValueSupplier.cs b/TestStack.Dossier/Suppliers/DefaultValueTypeValueSupplier.cs index 4495ffa..03ad33d 100644 --- a/TestStack.Dossier/Suppliers/DefaultValueTypeValueSupplier.cs +++ b/TestStack.Dossier/Suppliers/DefaultValueTypeValueSupplier.cs @@ -1,4 +1,7 @@ -using Ploeh.AutoFixture; +using System; +using System.Linq; +using Ploeh.AutoFixture; +using Ploeh.AutoFixture.Kernel; namespace TestStack.Dossier.Suppliers { @@ -13,10 +16,26 @@ public bool CanSupplyValue(string propertyName) return typeof (TValue).IsValueType; } + /// + public bool CanSupplyValue(Type type, string propertyName) + { + return type.IsValueType; + } + /// public TValue GenerateAnonymousValue(AnonymousValueFixture any, string propertyName) { return any.Fixture.Create(); } + + /// How to create weakly-typed CreateAnonymous with AutoFixture + /// http://autofixture.codeplex.com/workitem/4229 + /// + public object GenerateAnonymousValue(AnonymousValueFixture any, Type type, string propertyName) + { + var context = new SpecimenContext(any.Fixture); + var specimen = context.Resolve(type); + return specimen; + } } } diff --git a/TestStack.Dossier/TestDataBuilder.cs b/TestStack.Dossier/TestDataBuilder.cs index 078be5d..496a571 100644 --- a/TestStack.Dossier/TestDataBuilder.cs +++ b/TestStack.Dossier/TestDataBuilder.cs @@ -1,7 +1,8 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Linq.Expressions; +using System.Reflection; +using Ploeh.AutoFixture; using TestStack.Dossier.Lists; namespace TestStack.Dossier @@ -71,10 +72,22 @@ public static implicit operator List(TestDataBuilder } /// - /// Build the actual object - override this and call the constructor and any other methods. + /// Build the actual object - you can optionally override this and call the constructor and any other methods. /// /// The built object - protected abstract TObject BuildObject(); + protected virtual TObject BuildObject() + { + var model = Any.Fixture.Create(); + + var properties = typeof (TObject).GetProperties(BindingFlags.Public | BindingFlags.Instance); + foreach (var property in properties) + { + var val = Get(property.PropertyType, property.Name); + property.SetValue(model, val, null); + } + + return model; + } /// /// Return an NSubstitute proxy object when .Build() is called rather than a real object. @@ -120,6 +133,13 @@ public TValue Get(Expression> property) return (TValue)_properties[PropertyNameGetter.Get(property)]; } + public object Get(Type type, string propertyName) + { + if (!Has(propertyName)) + return Any.Get(type, propertyName); + return _properties[propertyName]; + } + /// /// Gets the recorded value for the given property from {TObject} or if no /// value has been recorded the default value for {TValue}. @@ -154,7 +174,17 @@ public static ListBuilder CreateListOfSize(int size) /// Whether or not there is a recorded value for the property protected bool Has(Expression> property) { - return _properties.ContainsKey(PropertyNameGetter.Get(property)); + return Has(PropertyNameGetter.Get(property)); + } + + /// + /// Returns whether or not there is currently an explicit value recorded against the given property from {TObject}. + /// + /// A string specifying the name of the property to retrieve the recorded value for + /// Whether or not there is a recorded value for the property + protected bool Has(string propertyName) + { + return _properties.ContainsKey(propertyName); } /// diff --git a/TestStack.Dossier/TestStack.Dossier.csproj b/TestStack.Dossier/TestStack.Dossier.csproj index 607d3e4..1b18a57 100644 --- a/TestStack.Dossier/TestStack.Dossier.csproj +++ b/TestStack.Dossier/TestStack.Dossier.csproj @@ -51,6 +51,7 @@ + From c57abec3a144a339c4807b3c1a6cbd13716b7aed Mon Sep 17 00:00:00 2001 From: Michael Whelan Date: Sun, 26 Apr 2015 11:30:20 +0100 Subject: [PATCH 02/13] renamed PropertyNameGetter to Reflector to show additional behaviour --- README.md | 1 + TestStack.Dossier/AnonymousValueFixture.cs | 2 +- TestStack.Dossier/PropertyNameGetter.cs | 50 ---------------------- TestStack.Dossier/ProxyBuilder.cs | 2 +- TestStack.Dossier/Reflector.cs | 30 +++++++++++++ TestStack.Dossier/TestDataBuilder.cs | 8 ++-- TestStack.Dossier/TestStack.Dossier.csproj | 2 +- 7 files changed, 38 insertions(+), 57 deletions(-) delete mode 100644 TestStack.Dossier/PropertyNameGetter.cs create mode 100644 TestStack.Dossier/Reflector.cs diff --git a/README.md b/README.md index 4851392..3eeb2f8 100644 --- a/README.md +++ b/README.md @@ -79,6 +79,7 @@ Prior to v2.0 this library was known as NTestDataBuilder. } } +Note that you can optionally override the `BuildObject` method if you want full control over how your object is constructed, for example if you want to use a particular constructor. If you don't provide this then Dossier will create the object for you. 3. Use the builder in a test, e.g. diff --git a/TestStack.Dossier/AnonymousValueFixture.cs b/TestStack.Dossier/AnonymousValueFixture.cs index fc0311d..b9bc447 100644 --- a/TestStack.Dossier/AnonymousValueFixture.cs +++ b/TestStack.Dossier/AnonymousValueFixture.cs @@ -82,7 +82,7 @@ public AnonymousValueFixture() /// The anonymous value, taking into account any registered conventions public T Get(Expression> property) { - var propertyName = PropertyNameGetter.Get(property); + var propertyName = Reflector.GetPropertyFor(property); var valueSupplier = LocalValueSuppliers .Concat(GlobalValueSuppliers) .Concat(DefaultValueSuppliers) diff --git a/TestStack.Dossier/PropertyNameGetter.cs b/TestStack.Dossier/PropertyNameGetter.cs deleted file mode 100644 index df0de58..0000000 --- a/TestStack.Dossier/PropertyNameGetter.cs +++ /dev/null @@ -1,50 +0,0 @@ -using System; -using System.Linq; -using System.Linq.Expressions; -using System.Reflection; - -namespace TestStack.Dossier -{ - internal static class PropertyNameGetter - { - public static string Get(Expression> property) - { - var memExp = property.Body as MemberExpression; - if (memExp == null) - throw new ArgumentException( - string.Format( - "Given property expression ({0}) didn't specify a property on {1}", - property, - typeof(TObject).Name - ), - "property" - ); - - return memExp.Member.Name; - } - - public static ConstructorInfo GetConstructor(Type type) - { - if (type == null) - throw new ArgumentNullException("type"); - - var ctors = type.GetConstructors() - .OrderByDescending(x => x.GetParameters().Length) - .ToArray(); - - if (ctors.Length == 0) - throw new InvalidOperationException(string.Format("The given type {0} does not contain any public constructors.", type.Name)); - - if (ctors.Length > 1 && ctors[0].GetParameters().Length == ctors[1].GetParameters().Length) - throw new InvalidOperationException(string.Format("Can't select best suited constructor between {0} and {1}.", GetConstructorSignature(ctors[0]), GetConstructorSignature(ctors[1]))); - - return ctors[0]; - } - - public static string GetConstructorSignature(ConstructorInfo ctor) - { - var typeName = ctor.DeclaringType == null ? "" : ctor.DeclaringType.Name; - return typeName + ctor.ToString().Substring("Void ".Length); - } - } -} diff --git a/TestStack.Dossier/ProxyBuilder.cs b/TestStack.Dossier/ProxyBuilder.cs index 306f79d..5a7ff05 100644 --- a/TestStack.Dossier/ProxyBuilder.cs +++ b/TestStack.Dossier/ProxyBuilder.cs @@ -29,7 +29,7 @@ public ProxyBuilder(Dictionary properties) public T Build() { var proxy = Substitute.For(); - var properties = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance); + var properties = Reflector.GetSettablePropertiesFor(); foreach (var property in properties.Where(property => _properties.ContainsKey(property.Name))) { if (property.GetGetMethod().IsVirtual) diff --git a/TestStack.Dossier/Reflector.cs b/TestStack.Dossier/Reflector.cs new file mode 100644 index 0000000..bd6c5c6 --- /dev/null +++ b/TestStack.Dossier/Reflector.cs @@ -0,0 +1,30 @@ +using System; +using System.Linq.Expressions; +using System.Reflection; + +namespace TestStack.Dossier +{ + internal static class Reflector + { + public static string GetPropertyFor(Expression> property) + { + var memExp = property.Body as MemberExpression; + if (memExp == null) + throw new ArgumentException( + string.Format( + "Given property expression ({0}) didn't specify a property on {1}", + property, + typeof(TObject).Name + ), + "property" + ); + + return memExp.Member.Name; + } + + public static PropertyInfo[] GetSettablePropertiesFor() + { + return typeof (TObject).GetProperties(BindingFlags.Public | BindingFlags.Instance); + } + } +} diff --git a/TestStack.Dossier/TestDataBuilder.cs b/TestStack.Dossier/TestDataBuilder.cs index 496a571..00ec434 100644 --- a/TestStack.Dossier/TestDataBuilder.cs +++ b/TestStack.Dossier/TestDataBuilder.cs @@ -79,7 +79,7 @@ protected virtual TObject BuildObject() { var model = Any.Fixture.Create(); - var properties = typeof (TObject).GetProperties(BindingFlags.Public | BindingFlags.Instance); + var properties = Reflector.GetSettablePropertiesFor(); foreach (var property in properties) { var val = Get(property.PropertyType, property.Name); @@ -114,7 +114,7 @@ protected virtual void AlterProxy(TObject proxy) {} /// The value to record public TBuilder Set(Expression> property, TValue value) { - _properties[PropertyNameGetter.Get(property)] = value; + _properties[Reflector.GetPropertyFor(property)] = value; return this as TBuilder; } @@ -130,7 +130,7 @@ public TValue Get(Expression> property) if (!Has(property)) return Any.Get(property); - return (TValue)_properties[PropertyNameGetter.Get(property)]; + return (TValue)_properties[Reflector.GetPropertyFor(property)]; } public object Get(Type type, string propertyName) @@ -174,7 +174,7 @@ public static ListBuilder CreateListOfSize(int size) /// Whether or not there is a recorded value for the property protected bool Has(Expression> property) { - return Has(PropertyNameGetter.Get(property)); + return Has(Reflector.GetPropertyFor(property)); } /// diff --git a/TestStack.Dossier/TestStack.Dossier.csproj b/TestStack.Dossier/TestStack.Dossier.csproj index 1b18a57..c7f8187 100644 --- a/TestStack.Dossier/TestStack.Dossier.csproj +++ b/TestStack.Dossier/TestStack.Dossier.csproj @@ -87,7 +87,7 @@ - + From 48efca48a214459e1a9725b5b5d0f33e89f24bb2 Mon Sep 17 00:00:00 2001 From: Michael Whelan Date: Sun, 26 Apr 2015 19:03:58 +0100 Subject: [PATCH 03/13] removed generic CanSupply from IAnonymousValueSupplier --- TestStack.Dossier/AnonymousValueFixture.cs | 2 +- TestStack.Dossier/IAnonymousValueSupplier.cs | 9 --------- TestStack.Dossier/Suppliers/DefaultEmailValueSupplier.cs | 6 ------ .../Suppliers/DefaultFirstNameValueSupplier.cs | 6 ------ .../Suppliers/DefaultLastNameValueSupplier.cs | 7 ------- .../Suppliers/DefaultStringValueSupplier.cs | 6 ------ TestStack.Dossier/Suppliers/DefaultValueSupplier.cs | 6 ------ .../Suppliers/DefaultValueTypeValueSupplier.cs | 6 ------ 8 files changed, 1 insertion(+), 47 deletions(-) diff --git a/TestStack.Dossier/AnonymousValueFixture.cs b/TestStack.Dossier/AnonymousValueFixture.cs index b9bc447..0d26193 100644 --- a/TestStack.Dossier/AnonymousValueFixture.cs +++ b/TestStack.Dossier/AnonymousValueFixture.cs @@ -86,7 +86,7 @@ public T Get(Expression> property) var valueSupplier = LocalValueSuppliers .Concat(GlobalValueSuppliers) .Concat(DefaultValueSuppliers) - .First(s => s.CanSupplyValue(propertyName)); + .First(s => s.CanSupplyValue(typeof(T), propertyName)); return valueSupplier.GenerateAnonymousValue(this, propertyName); } diff --git a/TestStack.Dossier/IAnonymousValueSupplier.cs b/TestStack.Dossier/IAnonymousValueSupplier.cs index 9ead160..493debc 100644 --- a/TestStack.Dossier/IAnonymousValueSupplier.cs +++ b/TestStack.Dossier/IAnonymousValueSupplier.cs @@ -7,15 +7,6 @@ namespace TestStack.Dossier /// public interface IAnonymousValueSupplier { - /// - /// Returns whether or not this supplier can supply an anonymous value for the given property. - /// - /// The type that the property is enclosed in - /// The type of the target property - the anonymous value will need to be of this type - /// The name of the property to generate a value for - /// Whether or not this supplier can supply an anonymous value - bool CanSupplyValue(string propertyName); - /// /// Returns whether or not this supplier can supply an anonymous value for the given property. /// diff --git a/TestStack.Dossier/Suppliers/DefaultEmailValueSupplier.cs b/TestStack.Dossier/Suppliers/DefaultEmailValueSupplier.cs index 9c1cd55..754faba 100644 --- a/TestStack.Dossier/Suppliers/DefaultEmailValueSupplier.cs +++ b/TestStack.Dossier/Suppliers/DefaultEmailValueSupplier.cs @@ -8,12 +8,6 @@ namespace TestStack.Dossier.Suppliers /// public class DefaultEmailValueSupplier : IAnonymousValueSupplier { - /// - public bool CanSupplyValue(string propertyName) - { - return CanSupplyValue(typeof(string), propertyName); - } - /// public bool CanSupplyValue(Type type, string propertyName) { diff --git a/TestStack.Dossier/Suppliers/DefaultFirstNameValueSupplier.cs b/TestStack.Dossier/Suppliers/DefaultFirstNameValueSupplier.cs index 2ab4fe8..bbd2e59 100644 --- a/TestStack.Dossier/Suppliers/DefaultFirstNameValueSupplier.cs +++ b/TestStack.Dossier/Suppliers/DefaultFirstNameValueSupplier.cs @@ -8,12 +8,6 @@ namespace TestStack.Dossier.Suppliers /// public class DefaultFirstNameValueSupplier : IAnonymousValueSupplier { - /// - public bool CanSupplyValue(string propertyName) - { - return CanSupplyValue(typeof (TValue), propertyName); - } - /// public bool CanSupplyValue(Type type, string propertyName) { diff --git a/TestStack.Dossier/Suppliers/DefaultLastNameValueSupplier.cs b/TestStack.Dossier/Suppliers/DefaultLastNameValueSupplier.cs index d188e23..e0fc9c7 100644 --- a/TestStack.Dossier/Suppliers/DefaultLastNameValueSupplier.cs +++ b/TestStack.Dossier/Suppliers/DefaultLastNameValueSupplier.cs @@ -8,13 +8,6 @@ namespace TestStack.Dossier.Suppliers /// public class DefaultLastNameValueSupplier : IAnonymousValueSupplier { - /// - public bool CanSupplyValue(string propertyName) - { - return typeof (TValue) == typeof(string) && - (propertyName.ToLower() == "lastname" || propertyName.ToLower() == "surname"); - } - /// public bool CanSupplyValue(Type type, string propertyName) { diff --git a/TestStack.Dossier/Suppliers/DefaultStringValueSupplier.cs b/TestStack.Dossier/Suppliers/DefaultStringValueSupplier.cs index 0381230..ed5b40f 100644 --- a/TestStack.Dossier/Suppliers/DefaultStringValueSupplier.cs +++ b/TestStack.Dossier/Suppliers/DefaultStringValueSupplier.cs @@ -8,12 +8,6 @@ namespace TestStack.Dossier.Suppliers /// public class DefaultStringValueSupplier : IAnonymousValueSupplier { - /// - public bool CanSupplyValue(string propertyName) - { - return typeof (TValue) == typeof(string); - } - /// public bool CanSupplyValue(Type type, string propertyName) { diff --git a/TestStack.Dossier/Suppliers/DefaultValueSupplier.cs b/TestStack.Dossier/Suppliers/DefaultValueSupplier.cs index 775c699..6bd6099 100644 --- a/TestStack.Dossier/Suppliers/DefaultValueSupplier.cs +++ b/TestStack.Dossier/Suppliers/DefaultValueSupplier.cs @@ -7,12 +7,6 @@ namespace TestStack.Dossier.Suppliers /// public class DefaultValueSupplier : IAnonymousValueSupplier { - /// - public bool CanSupplyValue(string propertyName) - { - return true; - } - /// public bool CanSupplyValue(Type type, string propertyName) { diff --git a/TestStack.Dossier/Suppliers/DefaultValueTypeValueSupplier.cs b/TestStack.Dossier/Suppliers/DefaultValueTypeValueSupplier.cs index 03ad33d..bf1cd68 100644 --- a/TestStack.Dossier/Suppliers/DefaultValueTypeValueSupplier.cs +++ b/TestStack.Dossier/Suppliers/DefaultValueTypeValueSupplier.cs @@ -10,12 +10,6 @@ namespace TestStack.Dossier.Suppliers /// public class DefaultValueTypeValueSupplier : IAnonymousValueSupplier { - /// - public bool CanSupplyValue(string propertyName) - { - return typeof (TValue).IsValueType; - } - /// public bool CanSupplyValue(Type type, string propertyName) { From 7632277d79a9ea83937d9b4bcf34ffbc282c456c Mon Sep 17 00:00:00 2001 From: Michael Whelan Date: Tue, 28 Apr 2015 19:32:53 +0100 Subject: [PATCH 04/13] Updated PR to apply Rob's suggestions. --- README.md | 2 +- TestStack.Dossier.Tests/BuildListTests.cs | 24 +--- TestStack.Dossier.Tests/BuildTests.cs | 2 +- .../BuilderBuildListTests.cs | 113 +++++++----------- TestStack.Dossier.Tests/BuilderBuildTests.cs | 16 ++- .../Builders/BasicCustomerBuilder.cs | 2 +- .../Builders/CustomerBuilder.cs | 2 +- .../Builders/ProxyAlteringCustomerBuilder.cs | 2 +- .../Builders/StudentViewModelBuilder.cs | 23 ++++ TestStack.Dossier.Tests/ProxyBuilderTests.cs | 2 +- .../{ => Stubs}/Entities/Company.cs | 2 +- .../{ => Stubs}/Entities/Customer.cs | 4 +- .../{ => Stubs}/Entities/CustomerClass.cs | 2 +- .../Stubs/ViewModels/Grade.cs | 7 ++ .../Stubs/ViewModels/InstructorViewModel.cs | 30 +++++ .../Stubs/ViewModels/StudentViewModel.cs | 35 ++++++ .../TestStack.Dossier.Tests.csproj | 11 +- TestStack.Dossier/AnonymousValueFixture.cs | 2 +- TestStack.Dossier/Reflector.cs | 2 +- TestStack.Dossier/TestDataBuilder.cs | 13 +- 20 files changed, 186 insertions(+), 110 deletions(-) create mode 100644 TestStack.Dossier.Tests/Builders/StudentViewModelBuilder.cs rename TestStack.Dossier.Tests/{ => Stubs}/Entities/Company.cs (86%) rename TestStack.Dossier.Tests/{ => Stubs}/Entities/Customer.cs (95%) rename TestStack.Dossier.Tests/{ => Stubs}/Entities/CustomerClass.cs (70%) create mode 100644 TestStack.Dossier.Tests/Stubs/ViewModels/Grade.cs create mode 100644 TestStack.Dossier.Tests/Stubs/ViewModels/InstructorViewModel.cs create mode 100644 TestStack.Dossier.Tests/Stubs/ViewModels/StudentViewModel.cs diff --git a/README.md b/README.md index 3eeb2f8..f0b394d 100644 --- a/README.md +++ b/README.md @@ -79,7 +79,7 @@ Prior to v2.0 this library was known as NTestDataBuilder. } } -Note that you can optionally override the `BuildObject` method if you want full control over how your object is constructed, for example if you want to use a particular constructor. If you don't provide this then Dossier will create the object for you. +Note that overriding the BuildObject is optional. It can be useful to do this if you want full control over how your object is constructed, for example if you want to use a particular constructor. If you don't choose to override this method then Dossier will create the object for you. 3. Use the builder in a test, e.g. diff --git a/TestStack.Dossier.Tests/BuildListTests.cs b/TestStack.Dossier.Tests/BuildListTests.cs index 2b498db..e2651b2 100644 --- a/TestStack.Dossier.Tests/BuildListTests.cs +++ b/TestStack.Dossier.Tests/BuildListTests.cs @@ -4,7 +4,7 @@ using TestStack.Dossier.DataSources.Generators; using TestStack.Dossier.Lists; using TestStack.Dossier.Tests.Builders; -using TestStack.Dossier.Tests.Entities; +using TestStack.Dossier.Tests.Stubs.Entities; using Xunit; namespace TestStack.Dossier.Tests @@ -70,16 +70,7 @@ public void GivenListOfBuilders_WhenCallingBuildListExplicitly_ThenAListOfUnique var entities = builders.BuildList(); - entities[0].ShouldNotBe(entities[1]); - entities[0].ShouldNotBe(entities[2]); - entities[0].ShouldNotBe(entities[3]); - entities[0].ShouldNotBe(entities[4]); - entities[1].ShouldNotBe(entities[2]); - entities[1].ShouldNotBe(entities[3]); - entities[1].ShouldNotBe(entities[4]); - entities[2].ShouldNotBe(entities[3]); - entities[2].ShouldNotBe(entities[4]); - entities[3].ShouldNotBe(entities[4]); + entities.ShouldBeUnique(); } [Fact] @@ -87,16 +78,7 @@ public void GivenListOfBuilders_WhenCallingBuildListImplicitly_ThenAListOfUnique { List entities = BasicCustomerBuilder.CreateListOfSize(5); - entities[0].ShouldNotBe(entities[1]); - entities[0].ShouldNotBe(entities[2]); - entities[0].ShouldNotBe(entities[3]); - entities[0].ShouldNotBe(entities[4]); - entities[1].ShouldNotBe(entities[2]); - entities[1].ShouldNotBe(entities[3]); - entities[1].ShouldNotBe(entities[4]); - entities[2].ShouldNotBe(entities[3]); - entities[2].ShouldNotBe(entities[4]); - entities[3].ShouldNotBe(entities[4]); + entities.ShouldBeUnique(); } [Fact] diff --git a/TestStack.Dossier.Tests/BuildTests.cs b/TestStack.Dossier.Tests/BuildTests.cs index c2fcdf6..f220d62 100644 --- a/TestStack.Dossier.Tests/BuildTests.cs +++ b/TestStack.Dossier.Tests/BuildTests.cs @@ -1,6 +1,6 @@ using Shouldly; using TestStack.Dossier.Tests.Builders; -using TestStack.Dossier.Tests.Entities; +using TestStack.Dossier.Tests.Stubs.Entities; using Xunit; namespace TestStack.Dossier.Tests diff --git a/TestStack.Dossier.Tests/BuilderBuildListTests.cs b/TestStack.Dossier.Tests/BuilderBuildListTests.cs index 658815e..458e112 100644 --- a/TestStack.Dossier.Tests/BuilderBuildListTests.cs +++ b/TestStack.Dossier.Tests/BuilderBuildListTests.cs @@ -1,20 +1,23 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Linq; using Shouldly; using TestStack.Dossier.DataSources.Generators; using TestStack.Dossier.Lists; using TestStack.Dossier.Tests.Builders; -using TestStack.Dossier.Tests.Entities; +using TestStack.Dossier.Tests.Stubs.ViewModels; using Xunit; namespace TestStack.Dossier.Tests { public class BuilderBuildListTests { + private DateTime _enrollmentDate = new DateTime(2004, 9, 9); + [Fact] public void GivenANormalBuilderInstance_WhenCallingIsListBuilderProxy_ThenReturnFalse() { - var builder = Builder.CreateNew(); + var builder = Builder.CreateNew(); builder.IsListBuilderProxy().ShouldBe(false); } @@ -22,7 +25,7 @@ public void GivenANormalBuilderInstance_WhenCallingIsListBuilderProxy_ThenReturn [Fact] public void GivenAListBuilderProxyInstance_WhenCallingIsListBuilderProxy_ThenReturnTrue() { - var builder = Builder.CreateListOfSize(1).TheFirst(1); + var builder = Builder.CreateListOfSize(1).TheFirst(1); builder.IsListBuilderProxy().ShouldBe(true); } @@ -30,7 +33,7 @@ public void GivenAListBuilderProxyInstance_WhenCallingIsListBuilderProxy_ThenRet [Fact] public void GivenListOfBuilders_WhenCallingBuildListExplicitly_ThenAListOfEntitiesOfTheRightSizeShouldBeReturned() { - var builders = Builder.CreateListOfSize(5); + var builders = Builder.CreateListOfSize(5); var entities = builders.BuildList(); @@ -40,7 +43,7 @@ public void GivenListOfBuilders_WhenCallingBuildListExplicitly_ThenAListOfEntiti [Fact] public void GivenListOfBuilders_WhenCallingBuildListImplicitly_ThenAListOfEntitiesOfTheRightSizeShouldBeReturned() { - List entities = Builder.CreateListOfSize(5); + List entities = Builder.CreateListOfSize(5); entities.Count.ShouldBe(5); } @@ -48,62 +51,44 @@ public void GivenListOfBuilders_WhenCallingBuildListImplicitly_ThenAListOfEntiti [Fact] public void GivenListOfBuilders_WhenCallingBuildListExplicitly_ThenAListOfEntitiesOfTheRightTypeShouldBeReturned() { - var builders = Builder.CreateListOfSize(5); + var builders = Builder.CreateListOfSize(5); var entities = builders.BuildList(); - entities.ShouldBeAssignableTo>(); + entities.ShouldBeAssignableTo>(); } [Fact] public void GivenListOfBuilders_WhenCallingBuildListImplicitly_ThenAListOfEntitiesOfTheRightTypeShouldBeReturned() { - List entities = Builder.CreateListOfSize(5); + List entities = Builder.CreateListOfSize(5); - entities.ShouldBeAssignableTo>(); + entities.ShouldBeAssignableTo>(); } [Fact] public void GivenListOfBuilders_WhenCallingBuildListExplicitly_ThenAListOfUniqueEntitiesShouldBeReturned() { - var builders = Builder.CreateListOfSize(5); + var builders = Builder.CreateListOfSize(5); var entities = builders.BuildList(); - entities[0].ShouldNotBe(entities[1]); - entities[0].ShouldNotBe(entities[2]); - entities[0].ShouldNotBe(entities[3]); - entities[0].ShouldNotBe(entities[4]); - entities[1].ShouldNotBe(entities[2]); - entities[1].ShouldNotBe(entities[3]); - entities[1].ShouldNotBe(entities[4]); - entities[2].ShouldNotBe(entities[3]); - entities[2].ShouldNotBe(entities[4]); - entities[3].ShouldNotBe(entities[4]); + entities.ShouldBeUnique(); } [Fact] public void GivenListOfBuilders_WhenCallingBuildListImplicitly_ThenAListOfUniqueEntitiesShouldBeReturned() { - List entities = Builder.CreateListOfSize(5); - - entities[0].ShouldNotBe(entities[1]); - entities[0].ShouldNotBe(entities[2]); - entities[0].ShouldNotBe(entities[3]); - entities[0].ShouldNotBe(entities[4]); - entities[1].ShouldNotBe(entities[2]); - entities[1].ShouldNotBe(entities[3]); - entities[1].ShouldNotBe(entities[4]); - entities[2].ShouldNotBe(entities[3]); - entities[2].ShouldNotBe(entities[4]); - entities[3].ShouldNotBe(entities[4]); + List entities = Builder.CreateListOfSize(5); + + entities.ShouldBeUnique(); } [Fact] public void GivenListOfBuildersWithCustomisation_WhenBuildingEntitiesExplicitly_ThenTheCustomisationShouldTakeEffect() { var generator = new SequentialGenerator(0, 100); - var list = CustomerBuilder.CreateListOfSize(3) + var list = StudentViewModelBuilder.CreateListOfSize(3) .All().With(b => b.WithFirstName(generator.Generate().ToString())); var data = list.BuildList(); @@ -117,7 +102,7 @@ public void GivenListOfBuildersWithCustomisation_WhenBuildingEntitiesImplicitly_ { var generator = new SequentialGenerator(0, 100); - List data = CustomerBuilder.CreateListOfSize(3) + List data = StudentViewModelBuilder.CreateListOfSize(3) .All().With(b => b.WithFirstName(generator.Generate().ToString())); data.Select(c => c.FirstName).ToArray() @@ -128,67 +113,59 @@ public void GivenListOfBuildersWithCustomisation_WhenBuildingEntitiesImplicitly_ public void GivenListOfBuildersWithARangeOfCustomisationMethods_WhenBuildingEntitiesExplicitly_ThenThenTheListIsBuiltAndModifiedCorrectly() { var i = 0; - var customers = CustomerBuilder.CreateListOfSize(5) + var studentViewModels = StudentViewModelBuilder.CreateListOfSize(5) .TheFirst(1).WithFirstName("First") .TheNext(1).WithLastName("Next Last") .TheLast(1).WithLastName("Last Last") .ThePrevious(2).With(b => b.WithLastName("last" + (++i).ToString())) - .All().WhoJoinedIn(1999) + .All().WhoEntrolledIn(_enrollmentDate) .BuildList(); - customers.ShouldBeAssignableTo>(); - customers.Count.ShouldBe(5); - customers[0].FirstName.ShouldBe("First"); - customers[1].LastName.ShouldBe("Next Last"); - customers[2].LastName.ShouldBe("last1"); - customers[3].LastName.ShouldBe("last2"); - customers[4].LastName.ShouldBe("Last Last"); - customers.ShouldAllBe(c => c.YearJoined == 1999); + studentViewModels.ShouldBeAssignableTo>(); + studentViewModels.Count.ShouldBe(5); + studentViewModels[0].FirstName.ShouldBe("First"); + studentViewModels[1].LastName.ShouldBe("Next Last"); + studentViewModels[2].LastName.ShouldBe("last1"); + studentViewModels[3].LastName.ShouldBe("last2"); + studentViewModels[4].LastName.ShouldBe("Last Last"); + studentViewModels.ShouldAllBe(c => c.EnrollmentDate == _enrollmentDate); } [Fact] public void GivenListOfBuildersWithARangeOfCustomisationMethods_WhenBuildingEntitiesImplicitly_ThenThenTheListIsBuiltAndModifiedCorrectly() { var i = 0; - List customers = CustomerBuilder.CreateListOfSize(5) + List studentViewModels = StudentViewModelBuilder.CreateListOfSize(5) .TheFirst(1).WithFirstName("First") .TheNext(1).WithLastName("Next Last") .TheLast(1).WithLastName("Last Last") .ThePrevious(2).With(b => b.WithLastName("last" + (++i).ToString())) - .All().WhoJoinedIn(1999); - - customers.ShouldBeAssignableTo>(); - customers.Count.ShouldBe(5); - customers[0].FirstName.ShouldBe("First"); - customers[1].LastName.ShouldBe("Next Last"); - customers[2].LastName.ShouldBe("last1"); - customers[3].LastName.ShouldBe("last2"); - customers[4].LastName.ShouldBe("Last Last"); - customers.ShouldAllBe(c => c.YearJoined == 1999); + .All().WhoEntrolledIn(_enrollmentDate); + + studentViewModels.ShouldBeAssignableTo>(); + studentViewModels.Count.ShouldBe(5); + studentViewModels[0].FirstName.ShouldBe("First"); + studentViewModels[1].LastName.ShouldBe("Next Last"); + studentViewModels[2].LastName.ShouldBe("last1"); + studentViewModels[3].LastName.ShouldBe("last2"); + studentViewModels[4].LastName.ShouldBe("Last Last"); + studentViewModels.ShouldAllBe(c => c.EnrollmentDate == _enrollmentDate); } [Fact] public void WhenBuildingEntitiesExplicitly_ThenTheAnonymousValueFixtureIsSharedAcrossBuilders() { - var customers = CustomerBuilder.CreateListOfSize(5).BuildList(); + var studentViewModels = StudentViewModelBuilder.CreateListOfSize(5).BuildList(); - customers[0].CustomerClass.ShouldBe(CustomerClass.Normal); - customers[1].CustomerClass.ShouldBe(CustomerClass.Bronze); - customers[2].CustomerClass.ShouldBe(CustomerClass.Silver); - customers[3].CustomerClass.ShouldBe(CustomerClass.Gold); - customers[4].CustomerClass.ShouldBe(CustomerClass.Platinum); + studentViewModels.Select(x => x.Grade).ShouldBeUnique(); } [Fact] public void WhenBuildingEntitiesImplicitly_ThenTheAnonymousValueFixtureIsSharedAcrossBuilders() { - List customers = CustomerBuilder.CreateListOfSize(5); + List studentViewModels = StudentViewModelBuilder.CreateListOfSize(5); - customers[0].CustomerClass.ShouldBe(CustomerClass.Normal); - customers[1].CustomerClass.ShouldBe(CustomerClass.Bronze); - customers[2].CustomerClass.ShouldBe(CustomerClass.Silver); - customers[3].CustomerClass.ShouldBe(CustomerClass.Gold); - customers[4].CustomerClass.ShouldBe(CustomerClass.Platinum); + studentViewModels.Select(x => x.Grade).ShouldBeUnique(); } } } \ No newline at end of file diff --git a/TestStack.Dossier.Tests/BuilderBuildTests.cs b/TestStack.Dossier.Tests/BuilderBuildTests.cs index 6b38f91..eb9829d 100644 --- a/TestStack.Dossier.Tests/BuilderBuildTests.cs +++ b/TestStack.Dossier.Tests/BuilderBuildTests.cs @@ -1,6 +1,7 @@ using Shouldly; using TestStack.Dossier.Tests.Builders; -using TestStack.Dossier.Tests.Entities; +using TestStack.Dossier.Tests.Stubs.Entities; +using TestStack.Dossier.Tests.Stubs.ViewModels; using Xunit; namespace TestStack.Dossier.Tests @@ -52,5 +53,18 @@ public void GivenBuilder_WhenCallingSetImplicitly_ShouldOverrideValues() customer.LastName.ShouldBe("Lanningham"); customer.YearJoined.ShouldBe(2014); } + + [Fact] + public void GivenBuilder_WhenBuildingObjectWithCtorAndPrivateSetters_ShouldSetPrivateSetters() + { + InstructorViewModel instructor = Builder.CreateNew() + .Set(x => x.FirstName, "Pi") + .Set(x => x.LastName, "Lanningham") + .Set(x => x.Id, 5); + + instructor.FirstName.ShouldBe("Pi"); + instructor.LastName.ShouldBe("Lanningham"); + instructor.Id.ShouldBe(5); + } } } \ No newline at end of file diff --git a/TestStack.Dossier.Tests/Builders/BasicCustomerBuilder.cs b/TestStack.Dossier.Tests/Builders/BasicCustomerBuilder.cs index df39128..dc6462f 100644 --- a/TestStack.Dossier.Tests/Builders/BasicCustomerBuilder.cs +++ b/TestStack.Dossier.Tests/Builders/BasicCustomerBuilder.cs @@ -1,6 +1,6 @@ using System; using System.Linq.Expressions; -using TestStack.Dossier.Tests.Entities; +using TestStack.Dossier.Tests.Stubs.Entities; namespace TestStack.Dossier.Tests.Builders { diff --git a/TestStack.Dossier.Tests/Builders/CustomerBuilder.cs b/TestStack.Dossier.Tests/Builders/CustomerBuilder.cs index 96e133c..319a57c 100644 --- a/TestStack.Dossier.Tests/Builders/CustomerBuilder.cs +++ b/TestStack.Dossier.Tests/Builders/CustomerBuilder.cs @@ -1,4 +1,4 @@ -using TestStack.Dossier.Tests.Entities; +using TestStack.Dossier.Tests.Stubs.Entities; namespace TestStack.Dossier.Tests.Builders { diff --git a/TestStack.Dossier.Tests/Builders/ProxyAlteringCustomerBuilder.cs b/TestStack.Dossier.Tests/Builders/ProxyAlteringCustomerBuilder.cs index 9272dd4..2419fdf 100644 --- a/TestStack.Dossier.Tests/Builders/ProxyAlteringCustomerBuilder.cs +++ b/TestStack.Dossier.Tests/Builders/ProxyAlteringCustomerBuilder.cs @@ -1,6 +1,6 @@ using System; using NSubstitute; -using TestStack.Dossier.Tests.Entities; +using TestStack.Dossier.Tests.Stubs.Entities; namespace TestStack.Dossier.Tests.Builders { diff --git a/TestStack.Dossier.Tests/Builders/StudentViewModelBuilder.cs b/TestStack.Dossier.Tests/Builders/StudentViewModelBuilder.cs new file mode 100644 index 0000000..9669a1d --- /dev/null +++ b/TestStack.Dossier.Tests/Builders/StudentViewModelBuilder.cs @@ -0,0 +1,23 @@ +using System; +using TestStack.Dossier.Tests.Stubs.ViewModels; + +namespace TestStack.Dossier.Tests.Builders +{ + public class StudentViewModelBuilder : TestDataBuilder + { + public virtual StudentViewModelBuilder WithFirstName(string firstName) + { + return Set(x => x.FirstName, firstName); + } + + public virtual StudentViewModelBuilder WithLastName(string lastName) + { + return Set(x => x.LastName, lastName); + } + + public virtual StudentViewModelBuilder WhoEntrolledIn(DateTime enrollmentDate) + { + return Set(x => x.EnrollmentDate, enrollmentDate); + } + } +} diff --git a/TestStack.Dossier.Tests/ProxyBuilderTests.cs b/TestStack.Dossier.Tests/ProxyBuilderTests.cs index e7aa540..ae9aef8 100644 --- a/TestStack.Dossier.Tests/ProxyBuilderTests.cs +++ b/TestStack.Dossier.Tests/ProxyBuilderTests.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using NSubstitute; using Shouldly; -using TestStack.Dossier.Tests.Entities; +using TestStack.Dossier.Tests.Stubs.Entities; using Xunit; namespace TestStack.Dossier.Tests diff --git a/TestStack.Dossier.Tests/Entities/Company.cs b/TestStack.Dossier.Tests/Stubs/Entities/Company.cs similarity index 86% rename from TestStack.Dossier.Tests/Entities/Company.cs rename to TestStack.Dossier.Tests/Stubs/Entities/Company.cs index 4e2dfbe..2635100 100644 --- a/TestStack.Dossier.Tests/Entities/Company.cs +++ b/TestStack.Dossier.Tests/Stubs/Entities/Company.cs @@ -1,4 +1,4 @@ -namespace TestStack.Dossier.Tests.Entities +namespace TestStack.Dossier.Tests.Stubs.Entities { public class Company { diff --git a/TestStack.Dossier.Tests/Entities/Customer.cs b/TestStack.Dossier.Tests/Stubs/Entities/Customer.cs similarity index 95% rename from TestStack.Dossier.Tests/Entities/Customer.cs rename to TestStack.Dossier.Tests/Stubs/Entities/Customer.cs index 5796b0d..0e71270 100644 --- a/TestStack.Dossier.Tests/Entities/Customer.cs +++ b/TestStack.Dossier.Tests/Stubs/Entities/Customer.cs @@ -1,6 +1,6 @@ -using System; +using System; -namespace TestStack.Dossier.Tests.Entities +namespace TestStack.Dossier.Tests.Stubs.Entities { public class Customer { diff --git a/TestStack.Dossier.Tests/Entities/CustomerClass.cs b/TestStack.Dossier.Tests/Stubs/Entities/CustomerClass.cs similarity index 70% rename from TestStack.Dossier.Tests/Entities/CustomerClass.cs rename to TestStack.Dossier.Tests/Stubs/Entities/CustomerClass.cs index 81f3956..dd79d7b 100644 --- a/TestStack.Dossier.Tests/Entities/CustomerClass.cs +++ b/TestStack.Dossier.Tests/Stubs/Entities/CustomerClass.cs @@ -1,4 +1,4 @@ -namespace TestStack.Dossier.Tests.Entities +namespace TestStack.Dossier.Tests.Stubs.Entities { public enum CustomerClass { diff --git a/TestStack.Dossier.Tests/Stubs/ViewModels/Grade.cs b/TestStack.Dossier.Tests/Stubs/ViewModels/Grade.cs new file mode 100644 index 0000000..8598bb2 --- /dev/null +++ b/TestStack.Dossier.Tests/Stubs/ViewModels/Grade.cs @@ -0,0 +1,7 @@ +namespace TestStack.Dossier.Tests.Stubs.ViewModels +{ + public enum Grade + { + A, B, C, D, F + } +} \ No newline at end of file diff --git a/TestStack.Dossier.Tests/Stubs/ViewModels/InstructorViewModel.cs b/TestStack.Dossier.Tests/Stubs/ViewModels/InstructorViewModel.cs new file mode 100644 index 0000000..44866e0 --- /dev/null +++ b/TestStack.Dossier.Tests/Stubs/ViewModels/InstructorViewModel.cs @@ -0,0 +1,30 @@ +using System; + +namespace TestStack.Dossier.Tests.Stubs.ViewModels +{ + public class InstructorViewModel + { + public InstructorViewModel(int id, string firstName, string lastName) + { + Id = id; + FirstName = firstName; + LastName = lastName; + } + + public int Id { get; private set; } + + public string LastName { get; private set; } + public string FirstName { get; private set; } + + public string FullName + { + get + { + return FirstName + " " + LastName; + } + } + public DateTime JoinDate { get; set; } + + public Grade Grade { get; set; } + } +} diff --git a/TestStack.Dossier.Tests/Stubs/ViewModels/StudentViewModel.cs b/TestStack.Dossier.Tests/Stubs/ViewModels/StudentViewModel.cs new file mode 100644 index 0000000..674a844 --- /dev/null +++ b/TestStack.Dossier.Tests/Stubs/ViewModels/StudentViewModel.cs @@ -0,0 +1,35 @@ +using System; +using System.ComponentModel.DataAnnotations; + +namespace TestStack.Dossier.Tests.Stubs.ViewModels +{ + public class StudentViewModel + { + public int Id { get; set; } + + [Required] + [StringLength(50)] + [Display(Name = "Last Name")] + public string LastName { get; set; } + [Required] + [StringLength(50, ErrorMessage = "First name cannot be longer than 50 characters.")] + [Display(Name = "First Name")] + public string FirstName { get; set; } + + [Display(Name = "Full Name")] + public string FullName + { + get + { + return FirstName + " " + LastName; + } + } + + [DataType(DataType.Date)] + [DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)] + [Display(Name = "Enrollment Date")] + public DateTime EnrollmentDate { get; set; } + + public Grade Grade { get; set; } + } +} diff --git a/TestStack.Dossier.Tests/TestStack.Dossier.Tests.csproj b/TestStack.Dossier.Tests/TestStack.Dossier.Tests.csproj index 0b2c2b0..43d79d9 100644 --- a/TestStack.Dossier.Tests/TestStack.Dossier.Tests.csproj +++ b/TestStack.Dossier.Tests/TestStack.Dossier.Tests.csproj @@ -44,6 +44,7 @@ ..\packages\Shouldly.2.4.0\lib\net40\Shouldly.dll + @@ -56,8 +57,11 @@ + - + + + @@ -77,13 +81,14 @@ - - + + + diff --git a/TestStack.Dossier/AnonymousValueFixture.cs b/TestStack.Dossier/AnonymousValueFixture.cs index 0d26193..9402247 100644 --- a/TestStack.Dossier/AnonymousValueFixture.cs +++ b/TestStack.Dossier/AnonymousValueFixture.cs @@ -82,7 +82,7 @@ public AnonymousValueFixture() /// The anonymous value, taking into account any registered conventions public T Get(Expression> property) { - var propertyName = Reflector.GetPropertyFor(property); + var propertyName = Reflector.GetPropertyNameFor(property); var valueSupplier = LocalValueSuppliers .Concat(GlobalValueSuppliers) .Concat(DefaultValueSuppliers) diff --git a/TestStack.Dossier/Reflector.cs b/TestStack.Dossier/Reflector.cs index bd6c5c6..5e3f51c 100644 --- a/TestStack.Dossier/Reflector.cs +++ b/TestStack.Dossier/Reflector.cs @@ -6,7 +6,7 @@ namespace TestStack.Dossier { internal static class Reflector { - public static string GetPropertyFor(Expression> property) + public static string GetPropertyNameFor(Expression> property) { var memExp = property.Body as MemberExpression; if (memExp == null) diff --git a/TestStack.Dossier/TestDataBuilder.cs b/TestStack.Dossier/TestDataBuilder.cs index 00ec434..5c93d42 100644 --- a/TestStack.Dossier/TestDataBuilder.cs +++ b/TestStack.Dossier/TestDataBuilder.cs @@ -82,8 +82,11 @@ protected virtual TObject BuildObject() var properties = Reflector.GetSettablePropertiesFor(); foreach (var property in properties) { - var val = Get(property.PropertyType, property.Name); - property.SetValue(model, val, null); + if (property.CanWrite) + { + var val = Get(property.PropertyType, property.Name); + property.SetValue(model, val, null); + } } return model; @@ -114,7 +117,7 @@ protected virtual void AlterProxy(TObject proxy) {} /// The value to record public TBuilder Set(Expression> property, TValue value) { - _properties[Reflector.GetPropertyFor(property)] = value; + _properties[Reflector.GetPropertyNameFor(property)] = value; return this as TBuilder; } @@ -130,7 +133,7 @@ public TValue Get(Expression> property) if (!Has(property)) return Any.Get(property); - return (TValue)_properties[Reflector.GetPropertyFor(property)]; + return (TValue)_properties[Reflector.GetPropertyNameFor(property)]; } public object Get(Type type, string propertyName) @@ -174,7 +177,7 @@ public static ListBuilder CreateListOfSize(int size) /// Whether or not there is a recorded value for the property protected bool Has(Expression> property) { - return Has(Reflector.GetPropertyFor(property)); + return Has(Reflector.GetPropertyNameFor(property)); } /// From 4607939ee3355419af0ac61c98011072f4af2f98 Mon Sep 17 00:00:00 2001 From: Bringer128 Date: Fri, 1 May 2015 12:58:24 +0800 Subject: [PATCH 05/13] Added a protected method called BuildByConstructor that allows a Builder to invoke an automated build of the object via a constructor. --- TestStack.Dossier.Tests/BuildTests.cs | 14 ++++++ .../AutoConstructorCustomerBuilder.cs | 32 +++++++++++++ .../TestStack.Dossier.Tests.csproj | 6 ++- TestStack.Dossier/TestDataBuilder.cs | 47 ++++++++++++++++++- 4 files changed, 96 insertions(+), 3 deletions(-) create mode 100644 TestStack.Dossier.Tests/Builders/AutoConstructorCustomerBuilder.cs diff --git a/TestStack.Dossier.Tests/BuildTests.cs b/TestStack.Dossier.Tests/BuildTests.cs index c2fcdf6..19242b3 100644 --- a/TestStack.Dossier.Tests/BuildTests.cs +++ b/TestStack.Dossier.Tests/BuildTests.cs @@ -80,5 +80,19 @@ public void GivenBuilder_WhenCallingSetImplicitly_ShouldOverrideValues() customer.LastName.ShouldBe("Lanningham"); customer.YearJoined.ShouldBe(2014); } + + [Fact] + public void GivenBuilderUsingConstructorReflection_WhenCallingBuildExplicitly_ShouldOverrideValues() + { + Customer customer = new AutoConstructorCustomerBuilder() + .WithFirstName("Bruce") + .WithLastName("Wayne") + .WhoJoinedIn(2012) + .Build(); + + customer.FirstName.ShouldBe("Bruce"); + customer.LastName.ShouldBe("Wayne"); + customer.YearJoined.ShouldBe(2012); + } } } \ No newline at end of file diff --git a/TestStack.Dossier.Tests/Builders/AutoConstructorCustomerBuilder.cs b/TestStack.Dossier.Tests/Builders/AutoConstructorCustomerBuilder.cs new file mode 100644 index 0000000..f1b7b09 --- /dev/null +++ b/TestStack.Dossier.Tests/Builders/AutoConstructorCustomerBuilder.cs @@ -0,0 +1,32 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using TestStack.Dossier.Tests.Entities; + +namespace TestStack.Dossier.Tests.Builders +{ + class AutoConstructorCustomerBuilder : TestDataBuilder + { + protected override Customer BuildObject() + { + return BuildByConstructor(); + } + + public AutoConstructorCustomerBuilder WithFirstName(string firstName) + { + return Set(x => x.FirstName, firstName); + } + + public AutoConstructorCustomerBuilder WithLastName(string lastName) + { + return Set(x => x.LastName, lastName); + } + + public AutoConstructorCustomerBuilder WhoJoinedIn(int year) + { + return Set(x => x.YearJoined, year); + } + } +} diff --git a/TestStack.Dossier.Tests/TestStack.Dossier.Tests.csproj b/TestStack.Dossier.Tests/TestStack.Dossier.Tests.csproj index 73d099b..97b84cd 100644 --- a/TestStack.Dossier.Tests/TestStack.Dossier.Tests.csproj +++ b/TestStack.Dossier.Tests/TestStack.Dossier.Tests.csproj @@ -13,7 +13,7 @@ 512 ..\ - d4853673 + 660882d1 true @@ -54,6 +54,7 @@ + @@ -100,6 +101,9 @@ PreserveNewest + + +