2015-02-21 5 views
5

Sto cercando di prendere in giro il metodo CreateAsync di UserStore per disporre di un archivio utente in memoria.Come simulare l'identità di Asp.net Il metodo CreateAsync di UserManager

public void Can_Create_User() 
{ 
    //Arrange 
    var dummyUser = new ApplicationUser() { UserName = "PinkWarrior", Email = "[email protected]" }; 
    var mockStore = new Mock<IUserStore<ApplicationUser>>(); 

    var userManager = new UserManager<ApplicationUser>(mockStore.Object); 
    mockStore.Setup(x => x.CreateAsync(dummyUser)) 
       .Returns(Task.FromResult(IdentityResult.Success)); 


    //Act 
    Task<IdentityResult> tt = (Task<IdentityResult>)mockStore.Object.CreateAsync(dummyUser); 
    var user = userManager.FindByName("PinkWarrior"); 

    //Assert 
    Assert.AreEqual("PinkWarrior", user.UserName); 
} 

Il user sopra è sempre nullo, perché non sono mai di inserirlo. Quindi il problema che ho è come posso rendere userManager, che non è un mock restituire un utente dal mio negozio finto?

This answer era un po 'simile ma non risponde alla mia domanda qui.

Qualsiasi aiuto molto apprezzato

risposta

13

È necessario prendere in giro la chiamata a FindByNameAsync, perché questo è ciò UserManager chiamerà:

public void Can_Create_User() 
{ 
    //Arrange 
    var dummyUser = new ApplicationUser() { UserName = "PinkWarrior", Email = "[email protected]" }; 
    var mockStore = new Mock<IUserStore<ApplicationUser>>(); 

    var userManager = new UserManager<ApplicationUser>(mockStore.Object); 
    mockStore.Setup(x => x.CreateAsync(dummyUser)) 
       .Returns(Task.FromResult(IdentityResult.Success)); 

    mockStore.Setup(x => x.FindByNameAsync(dummyUser.UserName)) 
       .Returns(Task.FromResult(dummyUser)); 


    //Act 
    Task<IdentityResult> tt = (Task<IdentityResult>)mockStore.Object.CreateAsync(dummyUser); 
    var user = userManager.FindByName("PinkWarrior"); 

    //Assert 
    Assert.AreEqual("PinkWarrior", user.UserName); 
} 

Tuttavia, credo che con questo test si sta testando Microsoft.AspNet.Identity.UserManager e non il codice. Quello che stai dimostrando è che UserManager chiama in qualche modo il tuo mockStore.

Source code for Microsoft.AspNet.Identity contiene questo tipo di test.

+0

Grazie, il tuo codice ha funzionato e il test passa ora, quindi ottieni i punti di merito :) yayy. Capisco che testare UserManager sia inutile, ma inizialmente avevo intenzione di deriderlo senza riflettere troppo. –

2

Il tuo negozio utente deriso non è stato preparato correttamente. Dato che si tratta di una simulazione, non dovresti aspettarti che lo mockStore.Object.CreateAsync possa fare qualsiasi cosa, vale a dire che sta per aggiungere qualcosa ovunque.

È necessario preparare l'operazione di "lettura" corrispondente, poiché molto probabilmente il gestore utenti la invocherà. (configura il metodo FindByNameAsync sul mock per restituire l'identità necessaria).

In ogni caso, quello che stai cercando di fare è inutile, mentre stai provando a testare un UserManager di classe framework.

Probabilmente ciò che è effettivamente necessario è prendere in giro il gestore utente stesso e utilizzare tale simulazione nel controller o ovunque si usi quel gestore utenti.

4

Controllare la classe MockHelper.cs dai test in Identity git repo

Identity GitHub repo link o Closed Issue for mocking

Si dovrebbe trovare ispirazioni per quanto riguarda prende in giro c'è, per esempio

public static UserManager<TUser> TestUserManager<TUser>(IUserStore<TUser> store = null) where TUser : class 
    { 
     store = store ?? new Mock<IUserStore<TUser>>().Object; 
     var options = new Mock<IOptions<IdentityOptions>>(); 
     var idOptions = new IdentityOptions(); 
     idOptions.Lockout.AllowedForNewUsers = false; 
     options.Setup(o => o.Value).Returns(idOptions); 
     var userValidators = new List<IUserValidator<TUser>>(); 
     var validator = new Mock<IUserValidator<TUser>>(); 
     userValidators.Add(validator.Object); 
     var pwdValidators = new List<PasswordValidator<TUser>>(); 
     pwdValidators.Add(new PasswordValidator<TUser>()); 
     var userManager = new UserManager<TUser>(store, options.Object, new PasswordHasher<TUser>(), 
      userValidators, pwdValidators, new UpperInvariantLookupNormalizer(), 
      new IdentityErrorDescriber(), null, 
      new Mock<ILogger<UserManager<TUser>>>().Object, 
      null); 
     validator.Setup(v => v.ValidateAsync(userManager, It.IsAny<TUser>())) 
      .Returns(Task.FromResult(IdentityResult.Success)).Verifiable(); 
     return userManager; 
    } 

im utilizzarlo con questo metodo:

 private UserController BuildCoontrollerWithDatabase() 
    { 
     DbContextOptionsBuilder dbContextOptionsBuilder = new DbContextOptionsBuilder(); 
     dbContextOptionsBuilder.UseInMemoryDatabase(); 

     ApplicationDbContext applicationDbContext = new ApplicationDbContext(dbContextOptionsBuilder.Options); 

     var userStore = new UserStore<ApplicationUser>(applicationDbContext); 

     UserManager<ApplicationUser> userManager = TestUserManager<ApplicationUser>(userStore); 

     return new UserController(userManager); 


    }