簡體   English   中英

c# - 單元測試、模擬和 ninject 工廠擴展

[英]c# - unit testing, mock and ninject factory extension

我有一個控制台應用程序,用戶可以在其中輸入一個數字,然后根據該數字生成一個功能。 Ninject.Extensions.Factory使用了Ninject.Extensions.Factory ,這里是綁定:

    Bind<IFeature>().To<FirstFeature>().Named("1");
    Bind<IFeature>().To<SecondFeature>().Named("2");
    Bind<IFeature>().To<ThirdFeature>().Named("3");
    Bind<IFeatureFactory>().ToFactory(() => new UseFirstArgumentAsNameInstanceProvider());

我要測試的代碼是:

構造函數:

public FeatureService(IFeatureFactory featureFactory, IUILayer uiHandler, int howManyFeatures)
    {
        this.featureFactory = featureFactory;
        this.uiHandler = uiHandler;
        this.howManyFeatures = howManyFeatures;
    }

被測方法:

public async Task startService()
    {
        bool isBadInput = false;
        string userSelection = null;
        uiHandler.displayMenu(howManyFeatures);
        userSelection = uiHandler.getSelection();
        while (!userSelection.Equals((howManyFeatures+1).ToString()))
        {
            IFeature feature = null;
            try
            {
                feature = featureFactory.createFeature(userSelection);
                isBadInput = false;
            }
            catch (ActivationException ex)
            {
                uiHandler.displayErrorMessage();
                isBadInput = true;
            }
            if (!isBadInput)
            {
                await feature.execFeature();
            }
            uiHandler.displayMenu(howManyFeatures);
            userSelection = uiHandler.getSelection();
        }
    }

如您所見,當我try createFeature ,我catchActivationException ,這意味着用戶輸入了無效的選擇(ninject 無法獲取具體類),並且沒有調用execFeature

我正在嘗試編寫一個單元測試來測試當用戶輸入有效選擇時,調用execFeature方法

這是測試:

    [TestMethod]
    public void WhenUserEnterValidSelectionExecFeatureCalled()
    {
        //Arrange
        Mock<IFeature> featureMock = new Mock<IFeature>();
        Mock<IConsoleService> consoleServiceMock = new Mock<IConsoleService>();
        // mock user input 7
        consoleServiceMock.Setup(c => c.ReadLine()).Returns("7");
        IUILayer uiLayer = new ConsoleUILayer(consoleServiceMock.Object);
        Mock<IFeatureFactory> featureFactory = new Mock<IFeatureFactory>();
        featureMock.Setup(t => t.execFeature());
        featureFactory.Setup(t => t.createFeature(It.IsAny<string>())).Returns(featureMock.Object);
        // init FeatureService with 3 features
        IFeatureService featureService = new FeatureService(featureFactory.Object, uiLayer, 3);

        //Act
        featureService.startService();

        //Assert
        featureMock.Verify(t => t.execFeature());
    }

正如你所看到的-我的創建consoleMock“7”的用戶輸入,而當我創建FeatureService我把3howManyFeatures -測試應該失敗(沒有具體的實現)。

現在,當我正常運行程序時 - 如果我輸入“7”,程序會按預期運行並輸出錯誤消息。

當我運行測試時,除了HowManyFeatures + 1之外, HowManyFeatures + 1每個輸入都通過了測試( HowManyFeatures +1失敗,因為它沒有進入while ),它不應該是這樣 - 它應該失敗的數字沒有具體的IFeature實現(只有 1、2 和 3 有具體的實現)。

我該如何解決這個問題? 我應該將Ninject Bindings “帶入” Tests項目嗎? 我什至應該測試這種方法嗎? 還是一切都沒用?

任何想法表示贊賞

您不需要將 ninject 綁定帶入您的測試,您的 FeatureService 不需要知道您的 IFeatureFactory 是基於 ninject 綁定,它並不關心它。
您需要做的是正確設置您的 IFeatureFacotory 模擬,現在無論輸入是什么,您的模擬都會返回相同的 IFeature,因為這是您告訴它使用的行為:

 featureFactory.Setup(t => t.createFeature(It.IsAny<string>())).Returns(featureMock.Object);

如果您希望它在獲取的數字大於 3 時拋出 ActivationException,只需設置此所需的行為即可:

featureFactory.Setup(t => t.createFeature(It.Is<string>(input => (int)input>3 ))).Throws(new ActivationException()); 

順便說一句,您可能應該直接模擬 IUiLayer 並將其注入到 FeatureService 而不是模擬您的 consoleService 並在您真正的 UiLayer 實現中使用它,這將使您的測試更加容易。

暫無
暫無

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

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