我正在尝试单元测试使用AutoMapping的UpdateUser控制器.这是控制器的代码
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 = "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你只是把它放在构造函数中.