我的问题并非试图简单地验证方法是否被调用。相反,我有一个方法在对象集合上工作,我想验证所有集合项目上的方法都被调用。使用Moq验证集合中的项目的方法
使用插件模型的示例,其中包含一个包含插件对象集合的插件管理器。每个插件都是PlugIn抽象基类的子类,它提供了一个抽象的Initialize方法。在我的测试中,我想确保每个插件都调用Initialize,而不管它们中的一个是否引发异常(只是大型测试套件的一部分)。
我最初的方法是创建一个mocked插件集合,然后配置被测试的类(PlugInManager)使用mocked对象。然后我通过调用应该遍历集合的PlugInManager.DoWork()来执行测试,并在每个项目上调用DoWork()。
完整的测试代码如下:
[TestMethod()]
public void MyTest()
{
// ARRANGE
var testParameter = new Something();
var mockPlugIns = new Collection<Mock<PlugIn>>()
{
new Mock<PlugIn>(),
new Mock<PlugIn>(),
new Mock<PlugIn>()
};
var plugIns = new Collection<PlugIn>();
foreach (var plugIn in mockPlugIns)
plugIns.Add(plugIn.Object);
var testManager = new PlugInManager()
{
PlugIns = plugIns
};
// ACT
testManager.DoWork(testParameter);
// ASSERT
foreach (var mockPlugIn in mockPlugIns)
mockPlugIn.Verify(plugin => plugin.DoWork(testParameter), Times.Once());
// Also tried using It.IsAny<Something>()
}
public abstract class PlugIn
{
abstract void DoWork(Something something);
}
public sealed class PlugInManager
{
public IEnumerable<PlugIn> PlugIns { get; set; }
public void DoWork(Something something)
{
foreach (var plugIn in PlugIns)
plugIn.DoWork(something);
}
}
不幸的是,验证失败的每个项目。
我已经浏览了代码,看到它实际上工作正常,并且每个项目都调用Initialize方法。那么,何时验证失败?
更新#1
我已经更新后显示整个测试方法在一个街区。我也改变了方法,需要一个参数,就像在我的真实代码中一样(现在)。
更新#2
运行测试时,收到的错误是:
Moq.MockException:
Expected invocation on the mock once, but was 0 times: plugin => plugin.DoWork(It.IsAny<Something>())
No setups configured.
No invocations performed.
如所提到的,当我通过单元测试步骤我看到,每个插件的实际被调用。然而,出于某种原因,Moq似乎没有注册或识别它。
更新#3
与测试代码的演出之后,我发现我可以使测试通过用一个简单的变化。该测试通过,如果我用下面的替换foreach循环的方法的中间:
plugIns.Add(mockPlugIns[0]);
plugIns.Add(mockPlugIns[1]);
plugIns.Add(mockPlugIns[2]);
我不明白这是怎么发挥作用,并最终喜欢做的项目数量动态的,所以在测试并不总是测试的情况下,有三个,所以使用foreach是我真正需要的。
任何想法?
这实际上并非如此,今天上午进一步测试后,我发现一切工作正常,与原始的foreach循环。我不知道发生了什么变化,但昨晚我尝试了许多不同的变体,而今天早上的代码看起来就像发布的内容一样,无论出于何种原因,测试现在都已经过去了!?!?!?!?
您能提供完整的测试或简化版吗?因为你的方法如果好,它应该工作。我还用你的代码创建了一个repro,它对我来说是绿色的。 – nemesv 2012-01-29 08:42:14