DEV Community

Cover image for SparkyTestHelpers: Mapping/AutoMapper
Brian Schroer
Brian Schroer

Posted on

SparkyTestHelpers: Mapping/AutoMapper

SparkyTestHelpers.Mapping:
NuGet package | Source Code | API documentation
SparkyTestHelpers.AutoMapper:
NuGet package | Source Code | API documentation

There aren’t many projects where you don’t have to “map” properties from one type to another. (I’m sorry if you’re a cartography fan who thought this would be about that kind of maps. 🗺)

Hand-written “destination.X = source.X;” code is a frequent source of bugs. It’s easy to accidentally code the wrong variable on one side or the other, or to miss properties. Tools like AutoMapper make it a lot easier to define mapping logic, but it’s still something that should be tested.

Wouldn’t it be nice if there was a unit testing tool that made map testing just as easy as AutoMapper makes mapping?

SparkyTestHelpers.Mapping

MapTester

class SparkyTestHelpers.Mapping.MapTester<TSource, TDestinatio>

This class is for testing that properties were successfully “mapped” from one type to another, using an AutoMapper-inspired fluent syntax (but your source/destination don’t have to be created via AutoMapper — It doesn’t care how the instances were created).

Methods

  • MapTester WithLogging(Action action)
    (optional) “Callback” action to log property values when asserting. If called without an action, defaults to Console.WriteLine.

  • MapTester IgnoringMember(Expression> destExpression)

  • MapMemberTester WhereMember(Expression> destExpression)

  • void AssertMappedValues(TSource source, TDestination dest)
    throws exception if any source/destination map validation specifications fail, or if any destination properties aren’t either tested or IgnoreMember’d.

Static Methods

  • MapTester ForMap()

Example

using SparkyTestHelpers.Mapping;
...
    Foo foo = CreateAndPopulateTestFoo();
    Bar bar = Mapper.Map<Foo, Bar>(foo); 

    MapTester.ForMap<Foo, Bar>()
        .IgnoringMember(dest => dest.DestOnlyProperty)
        .WhereMember(dest => dest.StatusCode).ShouldEqual(src => src.Status)
        .WhereMember(dest => dest.IsValid).ShouldEqualValue(true)
        .WhereMember(dest => dest.Percent).IsTestedBy((src, dest) => 
            Assert.AreEqual(src.Rate / 100, dest.Percent))
        .AssertMappedValues(foo, bar);
Enter fullscreen mode Exit fullscreen mode

You don’t have to configure anything for properties with the same name/type in the source and destination instances. AssertMappedValues() considers those successful if the source/destination values match.

Use IgnoringMember for destination properties that are not mapped, or which you need to test in another way.

Use WhereMember to “dot” to the ShouldEqual, ShouldEqualValue and IsTestedBy functions...

MapMemberTester

class SparkyTestHelpers.Mapping.MapMemberTester<TSource, TDestination>

This class is for testing that a property was successfully “mapped” from one type to another.

Methods

  • MapTester ShouldEqual(Expression> sourceExpression)
    use to verify destination property mapped from differently named source property(s)

  • MapTester ShouldEqualValue(Object value)
    use to verify destination property using a constant or some other value not derived from the source

  • MapTester IsTestedBy(Action customTest)
    use for custom complex validation that doesn’t fit one of the other verification methods

SparkyTestHelpers.AutoMapper

SparkyTestHelpers.Mapping extension methods for AutoMapper testing.

  • TDestination AssertAutoMappedValues(TSource source)
    calls Mapper.Map<TSource, TDestination>(source), then AssertMappedValues()

  • TDestination AssertAutoMappedRandomValues()
    uses SparkyTestHelpers.Populater to create a new TSource instance populated with random values, calls Mapper.Map<TSource, TDestination>(source), then AssertMappedValues().

Examples:

Create a test source instance, then call AssertAutoMappedValues to:

  • Use AutoMapper to map to a destination type instance
  • AssertMappedValues
using SparkyTestHelpers.AutoMapper;
...
Baz baz = CreateAndPopulateTestBax();
Qux qux = MapTester.ForMap<Baz, Qux>.AssertAutoMappedValues(baz);
Enter fullscreen mode Exit fullscreen mode

…or even better — with a single line of code:

  • Create a test source instance with randomly generated values
  • Use AutoMapper to map to a destination type instance
  • AssertMappedValues
using SparkyTestHelpers.AutoMapper;
...
MapTester.ForMap<Baz, Qux>.AssertAutoMappedRandomValues();
Enter fullscreen mode Exit fullscreen mode

Happy Testing!

Top comments (0)