无法使用Moq框架验证Select()内部调用的方法

时间:2018-05-16 11:08:29

标签: c# linq unit-testing moq verify

我在验证在LINQ Select()查询中的mock上调用了某个方法时遇到了问题。

以下是我想测试的ContentManager的方法:

public string ProcessElements(List<Item> items)
{
    var processed = items.Select(item => item.Process(Constants.Text));

    return Serialize(processed);
}

我想测试是否为列表的元素调用Process()。我的测试方法如下所示:

[TestMethod]
public void ProcessItems_ValidItems_ProcessCalled()
{
    var contentManager = new ContentManager();
    var itemMock = new Mock<Item>();
    itemMock.Setup(m => m.Process(It.IsAny<string>()))
        .Returns("serialized");

    contentManager.ProcessElements(new List<Item>() { itemMock.Object });

    itemMock.Verify(m => m.Process(It.IsAny<string>()), Times.Once());
}

当我运行此测试时,它会失败并返回以下消息:

  

测试方法ProcessItems_ValidItems_ProcessCalled抛出异常:

     

Moq.MockException:

     

模拟上的预期调用至少一次,但从未执行过:

     

m =&gt; m.Process(It.IsAny())

     

未配置任何设置。

     

没有进行任何调用。

如果我将Select()更改为foreach,则测试成功通过:

public string ProcessElements(List<Item> iitem)
{
    var processed = new List<string>();
    foreach (var item in iitem)
    {
        processed.Add(item.Process(Constants.Text));
    }

    return Serialize(processed);
}

Moq + Select()有什么问题?我该如何解决这个问题?

1 个答案:

答案 0 :(得分:7)

不确定.Serialize方法做什么,但.Select不运行实际查询,只返回知道如何遍历IEnumerable<T>的对象。

使用多个LINQ方法,例如.Where.Select,您可以构建通常稍后通过foreach或调用.ToList,{{1}进行延迟迭代的查询等等。

因此,要运行LINQ查询,请将其更改为:

.ToDictionary

TO:

.Select(...)