2016-07-26 22 views
5

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 SignInManagerHttpAuthenticationFeature 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.

cevap

0

Sadece SignInManager'la dalga geçebilir, servis koleksiyonuna yapıştırabilir ve denetleyiciniz için test etmek istediğiniz sonuçları döndürmek için bir aramayı _signInManager.PasswordSignInAsync(model.UserName, model.Password, model.RememberMe, lockoutOnFailure: false)'a ayarlayabilir misiniz?

+0

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