I am trying to use the unit test simple method, for example Login in my AccountController based on this test. MusiStore example .
// POST: /Account/Login [HttpPost] [AllowAnonymous] [ValidateAntiForgeryToken] public async Task<IActionResult> Login(LoginArgumentsModel model) { if (!ModelState.IsValid) { return BadRequest(); } var result = await _signInManager.PasswordSignInAsync(model.UserName, model.Password, model.RememberMe, lockoutOnFailure: false); if (result.Succeeded) { return Ok(); } return StatusCode(422); // Unprocessable Entity }
To do this, I need to use both UserManager and SignInManager , which ultimately forces me to use the entry for IAuthenticationHandler for use in the HttpAuthenticationFeature . At the end, the test is obtained as follows:
public class AccountControllerTestsFixture : IDisposable { public IServiceProvider BuildServiceProvider(IAuthenticationHandler handler) { var efServiceProvider = new ServiceCollection().AddEntityFrameworkInMemoryDatabase().BuildServiceProvider(); var services = new ServiceCollection(); services.AddOptions(); services.AddDbContext<ApplicationDbContext>(b => b.UseInMemoryDatabase().UseInternalServiceProvider(efServiceProvider)); services.AddIdentity<ApplicationUser, IdentityRole>(o => { o.Password.RequireDigit = false; o.Password.RequireLowercase = false; o.Password.RequireUppercase = false; o.Password.RequireNonAlphanumeric = false; o.Password.RequiredLength = 3; }).AddEntityFrameworkStores<ApplicationDbContext>();
and this:
public class AccountControllerTests : IClassFixture<AccountControllerTestsFixture> { private AccountControllerTestsFixture _fixture; public AccountControllerTests(AccountControllerTestsFixture fixture) { _fixture = fixture; } [Fact] public async Task Login_When_Present_Provider_Version() { // Arrange var mockedHandler = _fixture.MockSignInHandler(); IServiceProvider serviceProvider = _fixture.BuildServiceProvider(mockedHandler.Object); var userName = "Flattershy"; var userPassword = "Angel"; var claims = new List<Claim> { new Claim(ClaimTypes.NameIdentifier, userName) }; var userManager = serviceProvider.GetRequiredService<UserManager<ApplicationUser>>(); var userManagerResult = await userManager.CreateAsync(new ApplicationUser() { Id = userName, UserName = userName, TwoFactorEnabled = false }, userPassword); Assert.True(userManagerResult.Succeeded); var signInManager = serviceProvider.GetRequiredService<SignInManager<ApplicationUser>>(); AccountController controller = new AccountController(userManager, signInManager); // Act var model = new LoginArgumentsModel { UserName = userName, Password = userPassword }; var result = await controller.Login(model) as Microsoft.AspNetCore.Mvc.StatusCodeResult; // Assert Assert.Equal((int)System.Net.HttpStatusCode.OK, result.StatusCode); } }
Both multiple IAuthenticationHandler bullying and creating multiple classes that implement the IAuthenticationHandler for each test in different ways look too far for me, but I also want to use serviceProvider and don't want to scoff at the UserManager and SignInManager . Although the tests written in this way seem to work, I want to know if there is any complicated way to use the CookieAuthenticationHandler or anything else that behaves the way the application does with app.UseIdentity() .
source share