Unit Testing with xUnit and AutoMapper

xUnit is a unit testing framework which supports .NET Core . I use it to unit test my Document Controller WPF application (.NET Framework 4.6.1) and in this project, the AutoMapper is heavily used to map domain models to view models.

Photo by rawpixel on Unsplash

I wrote unit tests for each class and when the unit tests were run, I got the following error:

This error is due to the design of xUnit (Version 2.4.0) and AutoMapper (Version 7.0.1). xUnit groups tests (methods that have the attributes fact or theory) by their respective containing classes and runs the test groups concurrently in different threads.

I looked at my code and saw the initialisation of Mapper in the App class upon the start of the application:

public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
Mapper.Initialize(c => c.AddProfile<MappingProfile>());
}
}

And in order to use the Mapper instance in my WindowViewModel, I wrote the following code in each of the locations (view models) where AutoMapper was used:

public class WindowViewModel
{
private readonly IMapper mapper;
public WindowViewModel(ISomeService someService)
{
mapper = Mapper.Instance;
}
}

This gave the view model an instance of the initialised Mapper.

One issue with AutoMapper is that the Mapper initialisation can only be done once. As the unit tests run, the test runner went into the OnStartup method in the App class to attempt to initialise the Mapper in each thread. The first attempt succeeded but the subsequent attempt in the subsequent threads would fail.

To resolve this issue, instead of initialising the Mapper in the OnStartup method, I created the Mapper:

public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
Mapper = new MapperConfiguration(c =>
c.AddProfile<MappingProfile>()).CreateMapper();

}
}

And in my view models, I refactored the code to make use of dependency injection:

public class WindowViewModel
{
private readonly IMapper mapper;
public WindowViewModel(ISomeService someService, IMapper mapper)
{
this.mapper = mapper;
}
}

Of course, I needed to ensure the dependencies were injected when the view model was called:

        var mapper = (Application.Current as App).Mapper;
ViewModel = new WindowViewModel(someService, mapper);
}
}

After all of the refactoring, I ran my unit tests and all of them passed!

--

--

My journey as a self-taught developer. Feel free to drop by my online profile at tengweisong.com as well!

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Teng Wei Song

My journey as a self-taught developer. Feel free to drop by my online profile at tengweisong.com as well!