繁体   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