2013-05-08 28 views
14

我想單元測試使用AutoMapping的UpdateUser控制器。下面是控制器控制器上使用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); 
    } 

的代碼,這是我的單元測試 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); 
    } 

我有一個直覺,當以測試模式運行,該映射器不會查看我在Global.asax中設置的映射器配置。由於錯誤只發生在單元測試的執行過程中,而不是在原樣運行網站時發生。我已經創建了一個IMappaer接口作爲DI,因此我可以將它用於測試目的。我將Moq用作Mocking和xUnit作爲測試框架,我還安裝了我尚未使用的AutoMoq。任何想法?謝謝你看我冗長的帖子。希望有人能夠幫助,一直在撓頭,幾個小時,讀了很多帖子。

回答

17

在你的測試中,你需要創建一個你的IMapper接口的模擬版本,否則你不是單元測試,你是集成測試。那麼你只需要做一個簡單的mockMapper.Setup(m => m.Map(something, somethingElse)).Returns(anotherThing)

如果你想在測試中使用真正的AutoMapper實現,那麼你需要先設置它。你的測試不會自動提取你的Global.asax,你還必須在測試中設置映射。當我像這樣進行集成測試時,我通常會在測試夾具設置中調用靜態的AutoMapperConfiguration.Configure()方法。對於NUnit,這是[TestFixtureSetUp]方法,我認爲對於xUnit你只是把它放在構造函數中。

+2

嗨亞當,感謝您的迴應。我設法通過調用我在我的測試構造函數中在global.asax中創建的AutoMapperConfiguration.Configure()方法來修復它。 – Steven 2013-05-11 15:17:31

+2

在[TestFixtureSetUp]方法中有AutoMapperConfiguration.Configure(),我認爲這是最好的方法。 – Tun 2013-12-18 12:22:47

+0

對於我來說,我還必須指定程序集作爲自動映射器使用它自己的項目:AutoMapperConfiguration.ConfigureAutoMapper(typeof(someMappingConfig).Assembly) – RandomUs1r 2016-07-18 16:17:18