我正在尝试单元测试使用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你只是把它放在构造函数中.