0

这是我的控制器

    [POST("signup")]
    public virtual ActionResult Signup(UserRegisterViewModel user)
    {
        if (ModelState.IsValid)
        {
            var newUser = Mapper.Map<UserRegisterViewModel, User>(user);
            var confirmation = _userService.AddUser(newUser);

            if (confirmation.WasSuccessful)
                return RedirectToAction(MVC.Home.Index());
            else
                ModelState.AddModelError("Email", confirmation.Message);

        }
        return View(user);
    }

这是我的单元测试:

    [Test]
    public void Signup_Action_When_The_User_Model_Is_Valid_Returns_RedirectToRouteResult()
    {
        // Arrange
        const string expectedRouteName = "~/Views/Home/Index.cshtml";

        var registeredUser = new UserRegisterViewModel { Email = "newuser@test.com", Password = "123456789".Hash()};
        var confirmation = new ActionConfirmation<User>
                               {
                                   WasSuccessful = true,
                                   Message = "",
                                   Value = new User()
                               };
        _userService.Setup(r => r.AddUser(new User())).Returns(confirmation);

        _accountController = new AccountController(_userService.Object);

        // Act
        var result = _accountController.Signup(registeredUser) as RedirectToRouteResult;


        // Assert

        Assert.IsNotNull(result, "Should have returned a RedirectToRouteResult");
        Assert.AreEqual(expectedRouteName, result.RouteName, "Route name should be {0}", expectedRouteName);
    }

单元测试在这里失败了。

        var result = _accountController.Signup(registeredUser) as RedirectToRouteResult;

当我调试单元测试时,我收到以下错误消息:“缺少类型映射配置或不支持的映射。”

我认为这是因为配置在 web 项目中,而不是在单元测试项目中。我应该怎么做才能解决它?

4

3 回答 3

3

您需要配置映射器,因此在您的测试类设置中,而不是每个测试设置中,调用代码来设置映射。请注意,您可能还需要修改您对用户服务调用的期望,因为参数不匹配,即它们是不同的对象。可能您需要一个测试来检查对象的属性是否与传递给方法的模型的属性相匹配。

于 2012-07-19T02:30:13.883 回答
2

您应该真正使用映射引擎的接口,以便您可以模拟它而不是使用 AutoMapper,否则它是集成测试而不是单元测试。

AutoMapper 有一个名为的接口IMappingEngine,您可以使用如下所示的 IoC 容器将其注入到您的控制器中(此示例使用的是 StructureMap)。

class MyRegistry : Registry
{
    public MyRegistry()
    {
        For<IMyRepository>().Use<MyRepository>();
        For<ILogger>().Use<Logger>();

        Mapper.AddProfile(new AutoMapperProfile());
        For<IMappingEngine>().Use(() => Mapper.Engine);
    }
}

然后,您将能够使用依赖注入将 AutoMapper 的映射引擎注入您的控制器,允许您引用如下映射:

[POST("signup")]
public virtual ActionResult Signup(UserRegisterViewModel user)
{
    if (ModelState.IsValid)
    {
        var newUser = this.mappingEngine.Map<UserRegisterViewModel, User>(user);
        var confirmation = _userService.AddUser(newUser);

        if (confirmation.WasSuccessful)
            return RedirectToAction(MVC.Home.Index());
        else
            ModelState.AddModelError("Email", confirmation.Message);

    }
    return View(user);
}

您可以在此处阅读有关此内容的更多信息:如何使用 StructureMap 注入 AutoMapper IMappingEngine

于 2012-07-19T06:07:36.910 回答
0

将映射抽象到 MappingEngine 中可能很酷。

有时我对 IOC Automapper 使用以下方法

在 IOC 构建器中:

  builder.RegisterInstance(AutoMapperConfiguration.GetAutoMapper()).As<IMapper>();

其中 GetAutoMapper 是:

 public class AutoMapperConfiguration
    {
        public static IMapper GetAutoMapper()
        {
            var config = new MapperConfiguration(cfg =>
            {
                cfg.AddProfile<OrderModelMapperProfile>();
                cfg.AddProfile<OtherModelMapperProfile>();
                //etc;
               });
            var mapper = config.CreateMapper();
            return mapper;
        }
    }

最后在 Controller ctor

 public MyController(IMapper mapper)
        {
            _mapper = mapper;
        }
于 2017-09-01T16:17:24.600 回答