Asp.net-Mvc
使用 AutoMapper 對控制器進行單元測試
我正在嘗試對使用 AutoMapping 的 UpdateUser 控制器進行單元測試。這是控制器的程式碼
更新使用者控制器
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 = "user@username.com"; const string password = "password"; const string email = "email@email.com"; const string emailNew = "newEmail@email.com"; 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 for Mocking 和 xUnit 作為測試框架,我還安裝了尚未使用的 AutoMoq。任何想法?謝謝你看我的長文。希望有人可以提供幫助,一直在撓頭幾個小時並閱讀了很多文章。
在您的測試中,您需要創建
IMapper介面的模擬版本,否則您不是單元測試,而是集成測試。然後你只需要做一個簡單的mockMapper.Setup(m => m.Map(something, somethingElse)).Returns(anotherThing).如果你想在測試中使用真正的 AutoMapper 實現,那麼你需要先設置它。您的測試不會自動獲取您的
Global.asax,您還必須在測試中設置映射。當我像這樣進行集成測試時,我通常有一個AutoMapperConfiguration.Configure()在測試夾具設置中呼叫的靜態方法。對於 NUnit,這是[TestFixtureSetUp]方法,我認為對於 xUnit,您只需將其放在建構子中即可。