Skip to content

Commit

Permalink
Feature/type mapping (#64)
Browse files Browse the repository at this point in the history
* Added configuration support for type mappings.
* Removed obsolete members.
* Added initial type mapping support.
* Added ability to automatically resolve a type mapping.
* Added build log for when a type mapping has occurred.
* Added missing xmldoc comments.
* Updated TestData to pull data files from embedded resources directly rather than using the resources code gen class.
* Removed test case for decimal as it fails on current xunit
* Added license and updated documentation.
* Refactored CreateWith into Create.
* Added additional location data.
* Added type casting to better evaluate test results. (#63)
* Updated value generators to cache reference name matching expressions.
* Removed assembly scanning under full .net framework

+semver: breaking
  • Loading branch information
roryprimrose authored Apr 2, 2019
1 parent 3e18c2e commit 8313f09
Show file tree
Hide file tree
Showing 159 changed files with 4,730 additions and 1,700 deletions.
6 changes: 3 additions & 3 deletions GitVersion.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
mode: ContinuousDeployment
branches:
master:
tag: beta
hotfix:
tag: useBranchName
ignore:
sha: []
tag: useBranchName
21 changes: 21 additions & 0 deletions LICENSE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2016 Rory Primrose

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>netcoreapp1.0;net452</TargetFrameworks>
<TargetFrameworks>netcoreapp2.2;net452</TargetFrameworks>
<CodeAnalysisRuleSet>..\Solution Items\UnitTest.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="fluentassertions" Version="5.6.0" />
<PackageReference Include="nsubstitute" Version="3.1.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.9.0" />
<PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="2.9.0" />
<PackageReference Include="nsubstitute" Version="4.0.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.0.1" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.1">
<PrivateAssets>all</PrivateAssets>
Expand Down
47 changes: 23 additions & 24 deletions ModelBuilder.Synchronous.UnitTests/ScenarioTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ namespace ModelBuilder.Synchronous.UnitTests
using System.Reflection;
using FluentAssertions;
using ModelBuilder.UnitTests;
using ModelBuilder.UnitTests.Models;
using NSubstitute;
using Xunit;

Expand All @@ -23,8 +24,6 @@ public void CanAssignBuildStrategyTest()
{
var strategy = Substitute.For<IBuildStrategy>();

var existingStrategy = Model.BuildStrategy;

try
{
Model.BuildStrategy = strategy;
Expand All @@ -35,7 +34,7 @@ public void CanAssignBuildStrategyTest()
}
finally
{
Model.BuildStrategy = existingStrategy;
Model.BuildStrategy = Model.DefaultBuildStrategy;
}
}

Expand Down Expand Up @@ -86,25 +85,28 @@ public void CreateTUsesBuildStrategyToCreateInstanceTest()
}

[Fact]
public void CreateUsesBuildStrategyToCreateInstanceTest()
public void CreateTUsesBuildStrategyToCreateInstanceWithParametersTest()
{
var value = Guid.NewGuid();
var expected = new ReadOnlyModel(value);

var build = Substitute.For<IBuildStrategy>();
var generator = Substitute.For<IValueGenerator>();
var generators = new List<IValueGenerator> {generator}.AsReadOnly();
var creator = Substitute.For<ITypeCreator>();
var creators = new List<ITypeCreator> {creator}.AsReadOnly();

build.ValueGenerators.Returns(generators);
generator.IsSupported(typeof(Guid), null, Arg.Any<IBuildChain>()).Returns(true);
generator.Generate(typeof(Guid), null, Arg.Any<IExecuteStrategy>()).Returns(value);
build.TypeCreators.Returns(creators);
creator.CanCreate(typeof(ReadOnlyModel), null, Arg.Any<IBuildChain>()).Returns(true);
creator.CanPopulate(typeof(ReadOnlyModel), null, Arg.Any<IBuildChain>()).Returns(true);
creator.Create(typeof(ReadOnlyModel), null, Arg.Any<IExecuteStrategy>(), value).Returns(expected);
creator.Populate(expected, Arg.Any<IExecuteStrategy>()).Returns(expected);

try
{
Model.BuildStrategy = build;

var actual = Model.Create(typeof(Guid));
var actual = Model.Create<ReadOnlyModel>(value);

actual.Should().Be(value);
actual.Value.Should().Be(value);
}
finally
{
Expand All @@ -113,28 +115,25 @@ public void CreateUsesBuildStrategyToCreateInstanceTest()
}

[Fact]
public void CreateWithTUsesBuildStrategyToCreateInstanceWithParametersTest()
public void CreateUsesBuildStrategyToCreateInstanceTest()
{
var value = Guid.NewGuid();
var expected = new ReadOnlyModel(value);

var build = Substitute.For<IBuildStrategy>();
var creator = Substitute.For<ITypeCreator>();
var creators = new List<ITypeCreator> {creator}.AsReadOnly();
var generator = Substitute.For<IValueGenerator>();
var generators = new List<IValueGenerator> {generator}.AsReadOnly();

build.TypeCreators.Returns(creators);
creator.CanCreate(typeof(ReadOnlyModel), null, Arg.Any<IBuildChain>()).Returns(true);
creator.CanPopulate(typeof(ReadOnlyModel), null, Arg.Any<IBuildChain>()).Returns(true);
creator.Create(typeof(ReadOnlyModel), null, Arg.Any<IExecuteStrategy>(), value).Returns(expected);
creator.Populate(expected, Arg.Any<IExecuteStrategy>()).Returns(expected);
build.ValueGenerators.Returns(generators);
generator.IsSupported(typeof(Guid), null, Arg.Any<IBuildChain>()).Returns(true);
generator.Generate(typeof(Guid), null, Arg.Any<IExecuteStrategy>()).Returns(value);

try
{
Model.BuildStrategy = build;

var actual = Model.CreateWith<ReadOnlyModel>(value);
var actual = Model.Create(typeof(Guid));

actual.Value.Should().Be(value);
actual.Should().Be(value);
}
finally
{
Expand All @@ -143,7 +142,7 @@ public void CreateWithTUsesBuildStrategyToCreateInstanceWithParametersTest()
}

[Fact]
public void CreateWithUsesBuildStrategyToCreateInstanceWithParametersTest()
public void CreateUsesBuildStrategyToCreateInstanceWithParametersTest()
{
var value = Guid.NewGuid();
var expected = new ReadOnlyModel(value);
Expand All @@ -161,7 +160,7 @@ public void CreateWithUsesBuildStrategyToCreateInstanceWithParametersTest()
{
Model.BuildStrategy = build;

var actual = (ReadOnlyModel) Model.CreateWith(typeof(ReadOnlyModel), value);
var actual = (ReadOnlyModel) Model.Create(typeof(ReadOnlyModel), value);

actual.Value.Should().Be(value);
}
Expand Down
31 changes: 23 additions & 8 deletions ModelBuilder.UnitTests/AddressValueGeneratorTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ public void GenerateReturnsNullForAddressLinesBeyondSecondTest(string referenceN
}

[Fact]
public void GenerateReturnsRandomAddressTest()
public void GenerateReturnsRandomValueTest()
{
var buildChain = new BuildHistory();
var executeStrategy = Substitute.For<IExecuteStrategy>();
Expand All @@ -41,24 +41,38 @@ public void GenerateReturnsRandomAddressTest()

var target = new AddressValueGenerator();

var first = target.Generate(typeof(string), "address", executeStrategy) as string;

first.Should().NotBeNullOrWhiteSpace();
var first = (string) target.Generate(typeof(string), "address", executeStrategy) as string;

string second = null;

for (var index = 0; index < 1000; index++)
{
second = target.Generate(typeof(string), "address", executeStrategy) as string;
second = (string) target.Generate(typeof(string), "address", executeStrategy) as string;

if (first != second)
if (string.Equals(first, second, StringComparison.OrdinalIgnoreCase) == false)
{
break;
}
}

first.Should().NotBe(second);
}

[Fact]
public void GenerateReturnsStringValueTest()
{
var buildChain = new BuildHistory();
var executeStrategy = Substitute.For<IExecuteStrategy>();

executeStrategy.BuildChain.Returns(buildChain);

var target = new AddressValueGenerator();

var actual = target.Generate(typeof(string), "address", executeStrategy) as string;

actual.Should().BeOfType<string>();
actual.As<string>().Should().NotBeNullOrWhiteSpace();
}

[Theory]
[InlineData("address")]
Expand All @@ -82,8 +96,9 @@ public void GenerateReturnsStreetAddressTest(string propertyName)

actual.Should().NotBeNullOrWhiteSpace();

var matchingLocations =
TestData.Locations.Where(x => actual.Contains(x.StreetName) && actual.Contains(x.StreetSuffix));
var matchingLocations = TestData.Locations.Where(x =>
actual.Contains(x.StreetName, StringComparison.OrdinalIgnoreCase)
&& actual.Contains(x.StreetSuffix, StringComparison.OrdinalIgnoreCase));

matchingLocations.Should().NotBeEmpty();
}
Expand Down
42 changes: 13 additions & 29 deletions ModelBuilder.UnitTests/AgeValueGeneratorTests.cs
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
namespace ModelBuilder.UnitTests
{
using System;
using System.Globalization;
using FluentAssertions;
using NSubstitute;
using Xunit;

public class AgeValueGeneratorTests
{
[Theory]
[ClassData(typeof(NumericTypeDataSource))]
[ClassData(typeof(NumericTypeRangeDataSource))]
public void GenerateCanEvaluateManyTimesTest(Type type, bool typeSupported, double min, double max)
{
if (typeSupported == false)
Expand Down Expand Up @@ -45,7 +46,7 @@ public void GenerateCanEvaluateManyTimesTest(Type type, bool typeSupported, doub

value.Should().BeOfType(evaluateType);

var convertedValue = Convert.ToDouble(value);
var convertedValue = Convert.ToDouble(value, CultureInfo.InvariantCulture);

convertedValue.Should().BeGreaterOrEqualTo(min);
convertedValue.Should().BeLessOrEqualTo(max);
Expand Down Expand Up @@ -91,7 +92,7 @@ public void GenerateCanReturnNullAndNonNullValuesTest()

[Theory]
[ClassData(typeof(NumericTypeDataSource))]
public void GenerateReturnsNewValueTest(Type type, bool typeSupported, double min, double max)
public void GenerateReturnsNewValueTest(Type type, bool typeSupported)
{
if (typeSupported == false)
{
Expand Down Expand Up @@ -125,19 +126,14 @@ public void GenerateReturnsNewValueTest(Type type, bool typeSupported, double mi

value.Should().BeOfType(evaluateType);

var convertedValue = Convert.ToDouble(value);
var convertedValue = Convert.ToDouble(value, CultureInfo.InvariantCulture);

convertedValue.Should().BeLessOrEqualTo(target.MaxAge);
convertedValue.Should().BeGreaterOrEqualTo(1);
}

[Theory]
[ClassData(typeof(NumericTypeDataSource))]
public void GenerateThrowsExceptionWhenReferenceNotAgeTest(
Type type,
bool typeSupported,
double min,
double max)
[Fact]
public void GenerateThrowsExceptionWhenReferenceNotAgeTest()
{
var buildChain = new BuildHistory();
var executeStrategy = Substitute.For<IExecuteStrategy>();
Expand All @@ -146,14 +142,14 @@ public void GenerateThrowsExceptionWhenReferenceNotAgeTest(

var target = new AgeValueGenerator();

Action action = () => target.Generate(type, "Stuff", executeStrategy);
Action action = () => target.Generate(typeof(int), "Stuff", executeStrategy);

action.Should().Throw<NotSupportedException>();
}

[Theory]
[ClassData(typeof(NumericTypeDataSource))]
public void GenerateValidatesRequestedTypeTest(Type type, bool typeSupported, double min, double max)
public void GenerateValidatesRequestedTypeTest(Type type, bool typeSupported)
{
var executeStrategy = Substitute.For<IExecuteStrategy>();

Expand Down Expand Up @@ -186,7 +182,7 @@ public void HasHigherPriorityThanNumericValueGeneratorTest()

[Theory]
[ClassData(typeof(NumericTypeDataSource))]
public void IsSupportedEvaluatesRequestedTypeTest(Type type, bool typeSupported, double min, double max)
public void IsSupportedEvaluatesRequestedTypeTest(Type type, bool typeSupported)
{
var target = new AgeValueGenerator();

Expand All @@ -197,11 +193,7 @@ public void IsSupportedEvaluatesRequestedTypeTest(Type type, bool typeSupported,

[Theory]
[ClassData(typeof(NumericTypeDataSource))]
public void IsSupportedReturnsFalseWhenReferenceNameIsNullTest(
Type type,
bool typeSupported,
double min,
double max)
public void IsSupportedReturnsFalseWhenReferenceNameIsNullTest(Type type, bool typeSupported)
{
if (typeSupported == false)
{
Expand All @@ -218,11 +210,7 @@ public void IsSupportedReturnsFalseWhenReferenceNameIsNullTest(

[Theory]
[ClassData(typeof(NumericTypeDataSource))]
public void IsSupportedReturnsFalseWhenReferenceNameNotAgeTest(
Type type,
bool typeSupported,
double min,
double max)
public void IsSupportedReturnsFalseWhenReferenceNameNotAgeTest(Type type, bool typeSupported)
{
if (typeSupported == false)
{
Expand All @@ -239,11 +227,7 @@ public void IsSupportedReturnsFalseWhenReferenceNameNotAgeTest(

[Theory]
[ClassData(typeof(NumericTypeDataSource))]
public void IsSupportedReturnsTrueWhenReferenceNameIncludesAgeTest(
Type type,
bool typeSupported,
double min,
double max)
public void IsSupportedReturnsTrueWhenReferenceNameIncludesAgeTest(Type type, bool typeSupported)
{
if (typeSupported == false)
{
Expand Down
Loading

0 comments on commit 8313f09

Please sign in to comment.