Are you working on a project where you would like to add unit testing. Would you like to unit test controllers that depend upon a UserManager having been added to your dependency injection. Well I did and it took a bit of working out.
Setup
The first thing i did was create a new Asp .net core web application including asp .net identity. To keep things basic i followed this Introduction to Identity on ASP.NET Core this gave me a totally basic application web application with a single controller. I decided to add a new controller
[Route("api/[controller]")]
[ApiController]
public class CheckUserController : ControllerBase
{
private readonly UserManager _userManager;
public CheckUserController(UserManager userManager)
{
_userManager = userManager;
}
public async Task GetUser(string userId)
{
var user = await _userManager.FindByIdAsync(userId);
return user;
}
}}
The above controller has a single method GetUser which accepts a string being the user id and returns the user. Ideally something like this would be behind an authorize attribute but for testing purposes I left it out.
Test application Setup
I created a new project using xunit and included the test web project as a dependency. You will also need the following NugetPackages
- Microsoft.AspNetCore.Http.Abstractions
- Microsoft.Extensions.Logging.Abstractions
- Microsoft.Extensions.Options
- Moq
- xunit
- xunit.runner.visualstudio
Unit Test
The first thing we do is create a mock IUserStore to hold our users. We use the setup extension to add users to the store. Once that is done we can create new UserManager object passing it the store of users. This user manager can then be used to call the constructor on the controller which will then prepare it for our call to the actual action on the controller.
[Fact]
public async Task Test1()
{
// Arrange
var store = new Mock>();
store.Setup(x => x.FindByIdAsync("123", CancellationToken.None))
.ReturnsAsync(new IdentityUser()
{
UserName = "test@email.com",
Id = "123"
});
var mgr = new UserManager(store.Object, null, null, null, null, null, null, null, null);
var controller = new CheckUserController(mgr);
// Act
var result = await controller.GetUser("123");
// Assert
Assert.NotNull(result);
Assert.Equal("123", result.Id);
}
Conclusion
In order to unit test a controller you must instantiate the controller with all of the objects it requires to run. Normally these objects are passed in by dependency injection when creating unit tests we must create these ourselves by creating mock objects. This enables our unit tests to run on exactly the data we want to check, it also means that we dont need to have a database when unit testing we can mock the data that would normally have been returned by a database. You can find my question relating to this on Stack overflow How to mock UserManager