2013-05-08 18 views
14

'u kullanan denetleyicideki birim sınaması AutoMapping kullanan bir UpdateUser denetleyicisini test etmeye çalışıyorum. İşte kontrolörü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); 
    } 

kodudur ve bu benim Birim 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); 
    } 

olan bir bağırsak test modunda çalıştırıldığında hissediyorum var mapper, Global.asax'ta kurduğum mapper yapılandırmasına bakmıyor. Hata sadece ünite testinin yürütülmesi sırasında meydana geldiğinden, web sitesinin çalıştırıldığı sırada yapılmadığından ortaya çıkmaktadır. Bir IMappaer arabirimini DI olarak oluşturdum, böylece test amacıyla sahte olabilirim. Mocking for Mocking ve xUnit'i bir test çerçevesi olarak kullandım, henüz kullanmadığım AutoMoq'u da kurdum. Herhangi bir fikir? Uzun mesajıma baktığın için teşekkür ederim. Umarım birisi yardım edebilir, kafamı saatlerce çizebilir ve çok sayıda yazıyı okuyabilir.

cevap

17

Testinizde, IMapper arayüzünüzün alaylı bir versiyonunu oluşturmanız gerekir, aksi halde birim testi değilsiniz, entegrasyon testi sizsiniz. O zaman basit bir mockMapper.Setup(m => m.Map(something, somethingElse)).Returns(anotherThing) yapmalısınız.

Testlerinizde gerçek AutoMapper uygulamasını kullanmak istiyorsanız, önce bunu ayarlamanız gerekir. Testleriniz otomatik olarak Global.asax'u almaz, testlerde de eşlemeleri ayarlamanız gerekir. Böyle bir entegrasyon testi yaptığımda normalde test fikstür kurulumunda aradığım bir statik AutoMapperConfiguration.Configure() metoduna sahibim. NUnit için bu [TestFixtureSetUp] yöntemidir, xUnit için bunu sadece kurucunun içine koyduğunuzu düşünüyorum.

+2

Merhaba Adam, Yanıt verdiğiniz için teşekkür ederiz. Test kurucumda global.asax içinde oluşturduğum AutoMapperConfiguration.Configure() yöntemini çağırarak düzeltmeyi başardım. – Steven

+2

[TestFixtureSetUp] yönteminde AutoMapperConfiguration.Configure() öğesi olması, bunun en iyi yol olduğunu düşünüyorum. – Tun

+0

Benim için, otomatik eşleştiricim kendi projem olduğu için kullanılacak derlemeyi de belirtmem gerekiyordu: AutoMapperConfiguration.ConfigureAutoMapper (typeof (someMappingConfig) .Assembly) – RandomUs1r