2012-07-19 68 views
0

這裏是我的控制器當使用automapper時如何對單元測試控制器?

[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 = "[email protected]", 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項目中,而不是單元測試項目。我應該怎麼做才能解決它?

回答

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); 
} 

你可以閱讀更多關於此這裏:How to inject AutoMapper IMappingEngine with StructureMap

+1

一些代碼在這裏解釋你的意思是非常好的。 – 2012-11-17 13:08:20

+0

我一直在使用AutoMapper一年,並且我從未意識到IMappingEngine存在。我一直在嘲笑一切,但AutoMapper,並總是想知道爲什麼我的測試失敗,然後去看看,發現AutoMapper沒有配置。總是煩人。有界面會好得多:) – GetFuzzy 2014-05-24 21:13:05

3

您需要配置映射器,因此在您的測試類中設置,而不是按測試設置,調用代碼來設置映射。請注意,您可能還需要修改用戶服務調用的期望,因爲參數不匹配,即它們是不同的對象。可能你想要一個測試,檢查對象的屬性是否與傳遞給方法的模型的屬性相匹配。

0

抽象映射到MappingEngine可能很酷。

有時候我用下面的方法來IOC Automapper

在國際奧委會製造商:

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; 
     } 
    } 

最後在控制器構造函數

public MyController(IMapper mapper) 
     { 
      _mapper = mapper; 
     } 
相關問題