簡體   English   中英

Ninject內核綁定覆蓋

[英]Ninject kernel binding overrides

我只是想知道在內核中重新綁定綁定的最佳做法是什么。

我有一個帶有內核的類和一個帶有默認生產綁定的私有類模塊。

對於測試,我想覆蓋這些綁定,以便我可以交換我的Test Doubles / Mocks對象。

MyClass.Kernel.Load(new InlineModule(m=> m.Bind<IDepend>().To<TestDoubleDepend>()))

覆蓋IDepend的任何現有綁定?

我嘗試盡可能少地在我的代碼中直接使用DI內核,而不是依賴於構造函數注入(或選擇情況下的Attribute ,例如Attribute類)。 但是,我必須使用抽象層,以便我可以設置DI內核對象,使其在單元測試中可模擬。

例如:

public interface IDependencyResolver : IDisposable
{
    T GetImplementationOf<T>();
}

public static class DependencyResolver
{
    private static IDependencyResolver s_resolver;

    public static T GetImplementationOf<T>()
    {
        return s_resolver.GetImplementationOf<T>();
    }

    public static void RegisterResolver( IDependencyResolver resolver )
    {
        s_resolver = resolver;
    }

    public static void DisposeResolver()
    {
        s_resolver.Dispose();
    }
}

使用這樣的模式,您可以通過使用模擬或偽實現調用RegisterResolver來設置單元測試中的IDependencyResolver ,該實現返回您想要的任何對象,而無需連接完整模塊。 如果您將來選擇切換到另一個容器,它還具有從特定IoC容器中抽象代碼的第二個好處。

當然,您還需要根據需要向IDependencyResolver添加其他方法,我只是將這里的基礎知識作為示例。 是的,這將要求您在Ninject內核周圍編寫一個超級簡單的包裝器,它也實現了IDependencyResolver

你想要這樣做的原因是你的單元測試應該只測試一件事,並且通過使用你的實際IoC容器,你實際上比一個被測試的類更多地運動,這可能導致錯誤的負面因素,使你的測試脆弱和(更重要的是)隨着時間推移開發人員對其准確性的信心。 這可能導致測試冷漠和放棄,因為測試失敗但軟件仍然可以正常工作(“不用擔心,一個總是失敗,這不是什么大不了的事”)。

我只是希望這樣的事情有效

        var kernel = new StandardKernel(new ProductionModule(config));
        kernel.Rebind<ITimer>().To<TimerImpl>().InSingletonScope();

ProductionModule是我的生產綁定,我通過在特定測試用例中調用Rebind來覆蓋。 我在重新綁定的幾件物品上打電話重新綁定。

優點:如果有人向生產模塊添加了新的綁定,我會繼承它們,因此它不會以這種方式破壞,這可能很好。 這一切都適用於Java中的Guice ...希望它也可以在這里工作。

我傾向於做一個單獨的測試項目完成它自己的綁定 - 我當然假設我們正在談論某種單元測試。 測試項目使用自己的內核並將測試項目中的模塊加載到該內核中。 項目中的測試在CI構建期間執行,並通過構建腳本執行完整構建,但測試從未部署到生產中。

我意識到你的項目/解決方案設置可能不允許這種組織,但從我看到的看起來似乎很典型。

Peter Mayer的方法對於單元測試很有用,但恕我直言,使用構造函數/屬性注入手動注入Mock是不是更容易?

在我看來,對測試項目使用特定綁定對於其他類型的測試(集成,功能)更有用,但即使在這種情況下,您肯定需要根據測試更改綁定。

我的方法是某種kronhrbaugh和Hamish Smith的混合,創建了一個“依賴解析器”,你可以注冊和注銷要使用的模塊。

我會向MyClass添加一個接受模塊的構造函數。
這不會用於生產,但會用於測試。
在測試代​​碼中,我將傳遞一個模塊,該模塊定義了所需的測試雙精度數。

對於我正在進行的項目,我為每個環境(測試,開發,階段,生產等)創建了單獨的模塊。 這些模塊定義了綁定。

因為dev,stage和production都使用了許多相同的綁定,所以我創建了一個共同的模塊。 然后每個人都添加環境特定的綁定。

我還有一個KernelFactory,當傳遞一個環境令牌時,它將使用適當的模塊對一個IKernel進行假脫機。

這允許我切換我的環境令牌,這反過來會自動更改我的所有綁定。

但是如果這是用於單元測試的話,我同意上面的評論,即允許手動綁定的簡單構造函數是一種方法,因為它使Ninject遠離你的測試。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM