Unit Testing with xUnit and AutoMapper

Teng Wei Song
2 min readJan 5, 2019

--

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:

System.InvalidOperationException: 'Mapper already initialized. You must call Initialize once per application domain/process.'

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:

using AutoMapper;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:

using AutoMapper;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:

using AutoMapper;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:

using AutoMapper;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:

public partial class DocumentsWindow : Window
{
public DocumentsWindow()
{
InitializeComponent();
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!

--

--

Teng Wei Song

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