Skip to content

Commit

Permalink
Updated RelativeValueGenerator to support ExpandoObject context values
Browse files Browse the repository at this point in the history
Updated DefaultExecuteStrategy to use a temporary ExpandoObject to enable parameter dependent value generation
  • Loading branch information
roryprimrose committed Apr 25, 2020
1 parent 64852eb commit 03af4ee
Show file tree
Hide file tree
Showing 4 changed files with 350 additions and 127 deletions.
45 changes: 45 additions & 0 deletions ModelBuilder.UnitTests/Scenarios/RelativeDataGenerationTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
namespace ModelBuilder.UnitTests.Scenarios
{
using System.Diagnostics.CodeAnalysis;
using FluentAssertions;
using ModelBuilder.Data;
using ModelBuilder.UnitTests.Models;
using Xunit;

public class RelativeDataGenerationTests
{
[Fact]
[SuppressMessage("Globalization", "CA1308:Normalize strings to uppercase",
Justification = "Emails are lower-case by convention")]
public void AssignsPropertyValuesRelativeToOtherPropertyValues()
{
var actual = Model.Create<Person>();

var expected = (actual.FirstName + "." + actual.LastName + "@").ToLowerInvariant();

actual.PersonalEmail.Should()
.StartWith(expected);
}

[Fact]
[SuppressMessage("Globalization", "CA1308:Normalize strings to uppercase",
Justification = "Emails are lower-case by convention")]
public void CreatesParameterValuesRelativeToOtherParameterValues()
{
var actual = Model.Create<OrderedConstructorParameters>();

if (actual.Gender == Gender.Female)
{
TestData.FemaleNames.Should().Contain(actual.FirstName);
}
else
{
TestData.MaleNames.Should().Contain(actual.FirstName);
}

var expectedEmail = (actual.FirstName + "." + actual.LastName + "@" + actual.Domain).ToLowerInvariant();

actual.Email.Should().StartWith(expectedEmail);
}
}
}
161 changes: 137 additions & 24 deletions ModelBuilder.UnitTests/ValueGenerators/RelativeValueGeneratorTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
namespace ModelBuilder.UnitTests.ValueGenerators
{
using System;
using System.Collections.Generic;
using System.Dynamic;
using System.Text.RegularExpressions;
using FluentAssertions;
using FluentAssertions.Execution;
Expand All @@ -14,6 +14,112 @@ namespace ModelBuilder.UnitTests.ValueGenerators

public class RelativeValueGeneratorTests
{
[Fact]
public void GetValueReturnsDefaultValueWhenDeclaredPropertyNotFound()
{
var context = new Person
{
LastName = Guid.NewGuid().ToString()
};

var sut = new Wrapper<string>(
NameExpression.FirstName,
typeof(string));

var value = sut.ReadValue(NameExpression.Domain, context);

value.Should().BeNull();
}

[Fact]
public void GetValueReturnsDefaultValueWhenDynamicPropertyNotFound()
{
dynamic context = new ExpandoObject();

context.LastName = Guid.NewGuid().ToString();

var sut = new Wrapper<string>(
NameExpression.FirstName,
typeof(string));

var value = (string)sut.ReadValue(NameExpression.Domain, context);

value.Should().BeNull();
}

[Fact]
public void GetValueReturnsValueFromDeclaredProperty()
{
var context = new Person
{
LastName = Guid.NewGuid().ToString()
};

var sut = new Wrapper<string>(
NameExpression.FirstName,
typeof(string));

var value = sut.ReadValue(NameExpression.LastName, context);

value.Should().Be(context.LastName);
}

[Fact]
public void GetValueReturnsValueFromDynamicProperty()
{
dynamic context = new ExpandoObject();

context.LastName = Guid.NewGuid().ToString();

var sut = new Wrapper<string>(
NameExpression.FirstName,
typeof(string));

var value = (string)sut.ReadValue(NameExpression.LastName, context);

value.Should().Be(context.LastName);
}

[Theory]
[InlineData(null)]
[InlineData(123)]
public void GetValueReturnsValueFromNullableDeclaredProperty(int? expected)
{
var context = new RelativeNullableInt
{
YearLastUsed = expected
};
var expression = new Regex("YearLastUsed");

var sut = new Wrapper<int?>(
expression,
typeof(int?));

var actual = sut.ReadValue(expression, context);

actual.Should().Be(expected);
}

[Theory]
[InlineData(null)]
[InlineData(123)]
public void GetValueReturnsValueFromNullableDynamicProperty(int? expected)
{
dynamic context = new ExpandoObject();

context.YearLastUsed = expected;

var expression = new Regex("YearLastUsed");

var sut = new Wrapper<int?>(
expression,
typeof(int?));

var actual = (int?)sut.ReadValue(expression, context);

actual.Should().Be(expected);
}

[Fact]
public void GetValueThrowsExceptionWithNullContext()
{
Expand Down Expand Up @@ -160,14 +266,36 @@ public void IsMaleThrowsExceptionWithNullExecuteStrategy()
action.Should().Throw<ArgumentNullException>();
}

[Fact]
public void IsMatchReturnsTrueForMatchingExpandObject()
{
dynamic context = new ExpandoObject();
var buildChain = new BuildHistory();

context.FirstName = Guid.NewGuid().ToString();
context.LastName = string.Empty;

buildChain.Push(context);

var sut = new Wrapper<string>(NameExpression.FirstName, typeof(string));

var actual = sut.RunIsMatch(typeof(string), "FirstName", buildChain);

actual.Should().BeTrue();
}

[Theory]
[InlineData(typeof(bool), null, null, false)] // Type and name doesn't match
[InlineData(typeof(string), null, null, false)] // Name is null
[InlineData(typeof(string), "FirstName", null, false)] // No build context
[InlineData(typeof(string), "stuff", typeof(Person), false)] // Name doesn't match but we have an object to check for properties
[InlineData(typeof(string), "FirstName", typeof(Guid), false)] // Name matches but we don't have an object type to check for properties
[InlineData(typeof(string), "FirstName", typeof(int), false)] // Name matches but we don't have an object type to check for properties
[InlineData(typeof(string), "FirstName", typeof(string), false)] // Name matches but we don't have an object type to check for properties
[InlineData(typeof(string), "stuff", typeof(Person),
false)] // Name doesn't match but we have an object to check for properties
[InlineData(typeof(string), "FirstName", typeof(Guid),
false)] // Name matches but we don't have an object type to check for properties
[InlineData(typeof(string), "FirstName", typeof(int),
false)] // Name matches but we don't have an object type to check for properties
[InlineData(typeof(string), "FirstName", typeof(string),
false)] // Name matches but we don't have an object type to check for properties
[InlineData(typeof(string), "FirstName", typeof(Person), true)]
public void IsMatchReturnsWhetherScenarioSupported(
Type type,
Expand Down Expand Up @@ -200,21 +328,6 @@ public void IsMaleThrowsExceptionWithNullExecuteStrategy()
actual.Should().Be(expected);
}

[Fact]
public void IsMatchReturnsTrueWhenTargetExpressionMatchesReferenceName()
{
var context = new SlimModel();
var buildChain = new BuildHistory();

buildChain.Push(context);

var sut = new Wrapper<string>(NameExpression.FirstName, typeof(string));

var actual = sut.RunIsMatch(typeof(string), "FirstName", buildChain);

actual.Should().BeTrue();
}

[Fact]
public void IsMatchThrowsExceptionWithNullBuildChain()
{
Expand Down Expand Up @@ -245,22 +358,22 @@ public void IsMatchThrowsExceptionWithNullType()
}

[Fact]
public void ThrowsExceptionWithNullTargetExpressionAndTypes()
public void ThrowsExceptionWithNullTargetExpression()
{
// ReSharper disable once ObjectCreationAsStatement
#pragma warning disable CS8625 // Cannot convert null literal to non-nullable reference type.
Action action = () => new Wrapper<string>(null, typeof(string));
Action action = () => new Wrapper<string>(null);
#pragma warning restore CS8625 // Cannot convert null literal to non-nullable reference type.

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

[Fact]
public void ThrowsExceptionWithNullTargetExpression()
public void ThrowsExceptionWithNullTargetExpressionAndTypes()
{
// ReSharper disable once ObjectCreationAsStatement
#pragma warning disable CS8625 // Cannot convert null literal to non-nullable reference type.
Action action = () => new Wrapper<string>(null);
Action action = () => new Wrapper<string>(null, typeof(string));
#pragma warning restore CS8625 // Cannot convert null literal to non-nullable reference type.

action.Should().Throw<ArgumentException>();
Expand Down

0 comments on commit 03af4ee

Please sign in to comment.