4

正在嘗試Unity使用基於構造函數的DI之後的IoC。 問題是試圖讓集成測試工作。使用Unity IoC進行MVC集成測試

http://patrick.lioi.net/2013/06/20/streamlined-integration-tests/

「運行的集成測試應該保持儘可能多的真正的系統,在合理可能」

帕特里克上面介紹了MVC單元測試項目內建立一個IoC ..但我堅持以如何實現

public class HomeController : Controller 
{ 
    readonly IWinterDb db; 

    // Unity knows that if IWinterDb interface is asked for, it will inject in a new WinterDb() 
    public HomeController(IWinterDb db) 
    { 
     this.db = db; 
    } 

    public ActionResult Index() 
    { 
     var stories = db.Query<Story>() 
         .OrderByDescending(s => s.Rating) 
         .Include(s => s.StoryType); 

     return View(stories); 
    } 

單元測試都很好,傳遞一個假的:

[TestMethod] 
public void Index_GivenFake_ShouldReturn100Stories() 
{ 
    var db = new FakeWinterDb(); 
    db.AddSet(TestData.Stories); 
    var controller = new HomeController(db); 

    var result = controller.Index() as ViewResult; 
    var model = result.Model as IEnumerable<Story>; 

    Assert.AreEqual(100, model.Count()); 
} 

但是我喜歡它測試整個堆棧集成測試:

//Integration tests depend on the test data inserted in migrations 
[TestClass] 
public class HomeControllerTestsIntegration 
{ 
    [TestMethod] 
    public void Index_GivenNothing_ResultShouldNotBeNull() 
    { 
     var controller = new HomeController(); 

     var result = controller.Index() as ViewResult; 

     Assert.IsNotNull(result); 
    } 

問題:這不會編譯(因爲沒有參數的構造函數)。 Unity並沒有被調用來注入HomeController的正確依賴。

團結向上線:

public static class UnityConfig 
{ 
    public static void RegisterComponents() 
    { 
     var container = new UnityContainer(); 

     // register all your components with the container here 
     // it is NOT necessary to register your controllers 

     container.RegisterType<IWinterDb, WinterDb>(); 

     // for authentication 
     container.RegisterType<AccountController>(new InjectionConstructor()); 

     DependencyResolver.SetResolver(new UnityDependencyResolver(container)); 
    } 
} 

EDIT1:

[TestMethod] 
public void Index_GivenNothing_ResultShouldNotBeNull() 
{ 
    UnityConfig.RegisterComponents(); 
    var controller = UnityConfig.container.Resolve<HomeController>(); 

    var result = controller.Index() as ViewResult; 

    Assert.IsNotNull(result); 
} 

確保單身是存在的。

public static class UnityConfig 
{ 
    public static UnityContainer container; 

    public static void RegisterComponents() 
    { 
     container = new UnityContainer(); 

     // register all your components with the container here 
     // it is NOT necessary to register your controllers 

     //container.RegisterType<IWinterDb, WinterDb>(); 

     container.RegisterTypes(
      AllClasses.FromLoadedAssemblies(), 
      WithMappings.FromMatchingInterface, // Convention of an I in front of interface name 
      WithName.Default 
      ); // Default not a singleton in Unity 

     // for authentication 
     container.RegisterType<AccountController>(new InjectionConstructor()); 

     DependencyResolver.SetResolver(new UnityDependencyResolver(container)); 
    } 
} 

暴露團結的測試項目

回答

4

您需要通過集裝箱來解決您的控制器統一解決依賴你。

這可能是因爲更換這樣簡單:

var controller = new HomeController(); 

與此:

var controller = container.Resolve<HomeController>(); 

你顯然需要你的容器暴露在您的測試類。這是你在編寫生產代碼時通常不會做的事情。

+0

感謝菲爾 - 我已經在Edit1上面放了一些代碼。你的意思是「暴露你的容器」而不是控制器? –

+0

好的 - 我糾正了它。 –