ben MusiStore örnekten this testine dayanan benim AccountController
birim testine Login
böyle basit bir yöntem çalışıyorum ederken düzgün IAuthenticationHandler taklit etmek nasıl. Sonunda beni zorlar ki hem UserManager
ve SignInManager
HttpAuthenticationFeature
kullanmak için IAuthenticationHandler
için bir alternatif yazma kullanmak kullanmak gerekir Bunun içinbirim test ASP.NET Çekirdek kontrolör
// 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
}
. Sonunda Test böyle çıkıyor:
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>();
// IHttpContextAccessor is required for SignInManager, and UserManager
var context = new DefaultHttpContext();
context.Features.Set<IHttpAuthenticationFeature>(new HttpAuthenticationFeature { Handler = handler });
services.AddSingleton<IHttpContextAccessor>(new HttpContextAccessor()
{
HttpContext = context
});
return services.BuildServiceProvider();
}
public Mock<IAuthenticationHandler> MockSignInHandler()
{
var handler = new Mock<IAuthenticationHandler>();
handler.Setup(o => o.AuthenticateAsync(It.IsAny<AuthenticateContext>())).Returns<AuthenticateContext>(c =>
{
c.NotAuthenticated();
return Task.FromResult(0);
});
handler.Setup(o => o.SignInAsync(It.IsAny<SignInContext>())).Returns<SignInContext>(c =>
{
c.Accept();
return Task.FromResult(0);
});
return handler;
}
public void Dispose(){}
}
ve bu:
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);
}
}
İkisi birden IAuthenticationHandler
alay ve farklı bir şekilde her test için beni çok uzak biraz görünüyor için IAuthenticationHandler
uygulayan birden sınıflar oluşturarak, ama ben de hizmetProvider kullanmak istiyorum ve userManager
ve signInManager
alay etmek istemiyorum. Bu şekilde yazılmış testler işe yaramışken, CookieAuthenticationHandler
ya da app.UseIdentity()
ile uygulamanın yapılış şeklini değiştiren herhangi bir şey olup olmadığını anlamak için süper karmaşık bir yol olup olmadığını bilmek istiyorum.
Bunu birkaç kez yapabilirim ve bunu bana doğru hissetmiyor ve bence böyle bir çağrı alay konusu HttpContext'i etkilemeyecek ve böylece daha karmaşık bir denetçi uygun bir şekilde davranmayabilir. Ayrıca olabildiğince orijinal davranışa yakın olmasını istiyorum ve alaycı nesnelerde pek iyi değilim. – FluffyOwl