2013-05-08 18 views
14

Sto provando a testare un controller UpdateUser che utilizza AutoMapping. Ecco il codice per il controllerTest dell'unità sul controller che utilizza AutoMapper

UpdateUserController

private readonly IUnitOfWork _unitOfWork; 
    private readonly IWebSecurity _webSecurity; 
    private readonly IOAuthWebSecurity _oAuthWebSecurity; 
    private readonly IMapper _mapper; 

    public AccountController() 
    { 
     _unitOfWork = new UnitOfWork(); 
     _webSecurity = new WebSecurityWrapper(); 
     _oAuthWebSecurity = new OAuthWebSecurityWrapper(); 
     _mapper = new MapperWrapper(); 
    } 

    public AccountController(IUnitOfWork unitOfWork, IWebSecurity webSecurity, IOAuthWebSecurity oAuthWebSecurity, IMapper mapper) 
    { 
     _unitOfWork = unitOfWork; 
     _webSecurity = webSecurity; 
     _oAuthWebSecurity = oAuthWebSecurity; 
     _mapper = mapper; 
    } 

    // 
    // Post: /Account/UpdateUser 
    [HttpPost] 
    [ValidateAntiForgeryToken] 
    public ActionResult UpdateUser(UpdateUserModel model) 
    { 
     if (ModelState.IsValid) 
     { 
      // Attempt to register the user 
      try 
      { 
       var userToUpdate = _unitOfWork.UserRepository.GetByID(_webSecurity.CurrentUserId); 
       var mappedModel = _mapper.Map(model, userToUpdate); 

**mappedModel will return null when run in test but fine otherwise (e.g. debug)** 


       _unitOfWork.UserRepository.Update(mappedModel); 
       _unitOfWork.Save(); 

       return RedirectToAction("Index", "Home"); 
      } 
      catch (MembershipCreateUserException e) 
      { 
       ModelState.AddModelError("", ErrorCodeToString(e.StatusCode)); 
      } 
     } 
     return View(model); 
    } 

e questo è il mio Unit Test UpdateUserControllerTest

[Fact] 
    public void UserRepository_Update_User_Success() 
    { 
     Controller = new AccountController(UnitOfWork, WebSecurity.Object, OAuthWebSecurity.Object, Mapper); 
     const string emailAsUserName = "[email protected]"; 
     const string password = "password"; 
     const string email = "[email protected]"; 
     const string emailNew = "[email protected]"; 
     const string firstName = "first name"; 
     const string firstNameNew = "new first name"; 
     const string lastName = "last name"; 
     const string lastNameNew = "new last name"; 

     var updatedUser = new User 
      { 
       Email = emailNew, 
       FirstName = firstNameNew, 
       LastName = lastNameNew, 
       UserName = emailAsUserName 
      }; 

     WebSecurity.Setup(
      s => 
      s.CreateUserAndAccount(emailAsUserName, password, 
            new { FirstName = firstName, LastName = lastName, Email = email }, false)) 
        .Returns(emailAsUserName); 
     updatedUser.UserId = WebSecurity.Object.CurrentUserId; 

     UnitOfWork.UserRepository.Update(updatedUser); 
     UnitOfWork.Save(); 

     var actualUser = UnitOfWork.UserRepository.GetByID(updatedUser.UserId); 
     Assert.Equal(updatedUser, actualUser); 

     var model = new UpdateUserModel 
      { 
       Email = emailAsUserName, 
       ConfirmEmail = emailAsUserName, 
       FirstName = firstName, 
       LastName = lastName 
      }; 
     var result = Controller.UpdateUser(model) as RedirectToRouteResult; 
     Assert.NotNull(result); 
    } 

ho un intestino sensazione che se eseguito in modalità di prova, il mapper non guarda la configurazione del mapper che ho configurato in Global.asax. Poiché l'errore si verifica solo durante l'esecuzione del test unitario ma non durante l'esecuzione del sito web così com'è. Ho creato un'interfaccia IMappaer come DI in modo da poterla prendere in giro a scopo di test. Ho usato Moq for Mocking e xUnit come framework di test, ho anche installato AutoMoq che non ho ancora usato. Qualche idea? Grazie per aver guardato il mio lungo post. Spero che qualcuno possa aiutarti, mi ha grattato la testa per ore e ho letto un sacco di post.

risposta

17

Nel test è necessario creare una versione con derisione dell'interfaccia IMapper altrimenti non si sta testando l'unità, si sono test di integrazione. Quindi devi solo fare un semplice mockMapper.Setup(m => m.Map(something, somethingElse)).Returns(anotherThing).

Se si desidera utilizzare l'implementazione di AutoMapper reale nei test, è necessario prima configurarlo. I tuoi test non preleveranno automaticamente il tuo Global.asax, dovrai anche impostare i mapping nei test. Quando eseguo un test di integrazione come questo, normalmente ho un metodo statico AutoMapperConfiguration.Configure() che chiamo in una configurazione di test fixture. Per NUnit questo è il metodo [TestFixtureSetUp], penso che per xUnit tu lo abbia appena messo nel costruttore.

+2

Ciao Adam, grazie per aver risposto. Sono riuscito a risolverlo chiamando il metodo AutoMapperConfiguration.Configure() che ho creato in global.asax nel mio costruttore di test. – Steven

+2

Avendo AutoMapperConfiguration.Configure() nel metodo [TestFixtureSetUp], penso che questo sia il modo migliore di fare. – Tun

+0

Per quanto mi riguarda, ho dovuto specificare anche l'assembly da utilizzare in quanto il mio auto-mapper era il suo progetto: AutoMapperConfiguration.ConfigureAutoMapper (typeof (someMappingConfig) .Assembly) – RandomUs1r

Problemi correlati