[英]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
,我catch
了ActivationException
,这意味着用户输入了无效的选择(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
我把3在howManyFeatures
-测试应该失败(没有具体的实现)。
现在,当我正常运行程序时 - 如果我输入“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.