SparkyTestHelpers: Mapping/AutoMapper
Tags: csharp, dotnet, testing, automapper
Published: 2020-02-23 01:18:10

> SparkyTestHelpers.Mapping:
[NuGet package](https://www.nuget.org/packages/SparkyTestHelpers.Mapping) | [Source Code](https://github.com/BrianSchroer/sparky-test-helpers/tree/master/SparkyTestHelpers.Mapping) | [API documentation](https://github.com/BrianSchroer/sparky-test-helpers/blob/master/SparkyTestHelpers.Mapping/api.md)
SparkyTestHelpers.AutoMapper:
[NuGet package](https://www.nuget.org/packages/SparkyTestHelpers.AutoMapper/) | [Source Code](https://github.com/BrianSchroer/sparky-test-helpers/tree/master/SparkyTestHelpers.AutoMapper) | [API documentation](https://github.com/BrianSchroer/sparky-test-helpers/blob/master/SparkyTestHelpers.AutoMapper/api.md)

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](http://automapper.org/) 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<TSource, TDestination>

*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<TSource, TDestination>* **WithLogging**(*Action<String> action*)
(optional) “Callback” action to log property values when asserting. If called without an action, defaults to Console.WriteLine.

- *MapTester<TSource, TDestination>* **IgnoringMember**(*Expression<Func<TDestination, Object>> destExpression*)

- *MapMemberTester<TSource, TDestination>* **WhereMember**(*Expression<Func<TDestination, Object>> 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<TSource, TDestination>* **ForMap**()

###Example

```csharp
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);
```

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<TSource, TDestination>

*class* **SparkyTestHelpers.Mapping.MapMemberTester**<*TSource, TDestination*>

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

###Methods

- *MapTester<TSource, TDestination>* **ShouldEqual**(*Expression<Func<TSource, Object>> sourceExpression*)
use to verify destination property mapped from differently named source property(s)

- *MapTester<TSource, TDestination>* **ShouldEqualValue**(*Object value*)
use to verify destination property using a constant or some other value not derived from the source

- *MapTester<TSource, TDestination>* **IsTestedBy**(*Action<TSource, TDestination> 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](https://www.nuget.org/packages/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**

```csharp
using SparkyTestHelpers.AutoMapper;
...
Baz baz = CreateAndPopulateTestBax();
Qux qux = MapTester.ForMap<Baz, Qux>.AssertAutoMappedValues(baz);
```

…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**

```csharp
using SparkyTestHelpers.AutoMapper;
...
MapTester.ForMap<Baz, Qux>.AssertAutoMappedRandomValues();
```
- - -
Happy Testing!