I am trying to work out how to add unit testing to my project. I thought it was best to start with a blank project and work it out from the start rather than adding it to my main project. Once I understand the process i figure i can start refactoring my project for adding testing.
So i created a web application and added default user identity to it.
This gave me a start up looking like this
public void ConfigureServices(IServiceCollection services)
{
services.Configure<CookiePolicyOptions>(options =>
{
// This lambda determines whether user consent for non-essential cookies is needed for a given request.
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
});
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(
Configuration.GetConnectionString("DefaultConnection")));
services.AddDefaultIdentity<IdentityUser>()
.AddEntityFrameworkStores<ApplicationDbContext>();
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
}
Then i created a simple controller and passed the usermanager in the constructor.
[Route("api/[controller]")]
[ApiController]
public class SweetController : ControllerBase
{
private readonly UserManager<IdentityUser> _userManager;
public SweetController(UserManager<IdentityUser> userManager)
{
_userManager = userManager;
}
public async Task<int> NumberOfGummyBearsForUser(string userId)
{
var user = await _userManager.FindByIdAsync(userId);
var userHasASweetTooth = await _userManager.IsInRoleAsync(user, "SweetTooth");
if (userHasASweetTooth)
{
return 100;
}
else
{
return 1;
}
}
}
The first thing i have been trying to do is mock this user manager but its not working.
public void Test1()
{
// Arrange
var mockUser = new Mock<UserManager<IdentityUser>>();
var userManager = new UserManager(mockRepo.Object); <-- error here see image below
var controller = new SweetController(userManager.Object);
// Act
var result = await controller.NumberOfGummyBearsForUser("123");
// Assert
Assert.Equal(100, result);
}
The error looks like this
I think i need to pass more to create this usermanager object but i am not sure what all the tutorials i have found use ApplicationUser and not IdentityUser so i am at a loss as to how i can mock this object.
You just do
// Arrange
var mockUser = new Mock<UserManager<IdentityUser>>();
var controller = new SweetController(mockUser.Object);
You don't need
var userManager = new UserManager(mockRepo.Object); <-- error here see image below
at all. mockUser
is already the mocked UserManager<T>
, which you place a mocked instance via mock.Object
.
When you mock an object you don't have to instantiate it with all of its dependencies (that would be integration test), that's the point of mocking (along with making methods return a desired value and do behavior tests to make sure your tested code has called a specific method with specific parameter of the mocked object).
Of course per se the above code won't work, since you didn't setup any test conditions/returns for FindByIdAsync
and IsInRoleAsync
. You have to setup these with
mockUser.Setup( userManager => userManager.FindByIdAsync(It.IsAny<string>()))
.ReturnsAsync(new IdentityUser { ... });
mockUser.Setup( userManager => userManager.IsInRoleAsync(It.IsAny<IdentityUser>(), "SweetTooth"))
.ReturnsAsync(true);
Then whenever the mock is called it returns your predefined user and a predefined result.
With Tseng's help I got this working. A fully working version of this is
private readonly UserManager<IdentityUser> _userManager;
public SweetController(UserManager<IdentityUser> userManager)
{
_userManager = userManager;
}
public async Task<IdentityUser> GetUser(string userId)
{
var user = await _userManager.FindByIdAsync(userId);
return user;
}
[Fact]
public async Task Test1()
{
// Arrange
var store = new Mock<IUserStore<IdentityUser>>();
store.Setup(x => x.FindByIdAsync("123", CancellationToken.None))
.ReturnsAsync(new IdentityUser()
{
UserName = "[email protected]",
Id = "123"
});
var mgr = new UserManager<IdentityUser>(store.Object, null, null, null, null, null, null, null, null);
var controller = new SweetController(mgr);
// Act
var result = await controller.GetUser("123");
// Assert
Assert.NotNull(result);
Assert.Equal("123", result.Id);
}
I removed the role check just to get it working as basic as possible.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With