使用Moq在C#中设置索引器

时间:2010-05-26 20:05:00

标签: c# unit-testing moq indexer

我无法弄清楚如何使用Moq在C#中设置indexers。 Moq文档很薄弱,我已经做了很多搜索......我想做的事情与How to Moq Setting an Indexed property的解决方案类似:

var someClass = new Mock<ISomeClass>();
someClass.SetupSet(o => o.SomeIndexedProperty[3] = 25);

我想修改上面的内容以适用于任何索引和任何值,所以我可以这样做:

someClass.Object.SomeIndexedProperty[1] = 5;

目前我有以下内容,它对索引属性getter非常有用,但是如果我设置了值,Moq会忽略它:

var someValues = new int[] { 10, 20, 30, 40 };
var someClass = new Mock<ISomeClass>();
someClass.Setup(o => o.SomeIndexedProperty[It.IsAny<int>()])
    .Returns<int>(index => someValues[index]);

// Moq doesn't set the value below, so the Assert fails!
someClass.Object.SomeIndexedProperty[3] = 25;
Assert.AreEqual(25, someClass.Object.SomeIndexedProperty[3]);

3 个答案:

答案 0 :(得分:11)

我找到了解决问题的方法。它需要改变我的想法...我一直在寻找使用NUnit的Assert来验证我的someClass模拟中的索引器设置器是否被调用了正确的值。

似乎使用Moq支持的方法是使用VerifySet函数。一个人为的例子:

someClass.Object.SomeIndexedProperty[3] = 25;
someClass.VerifySet(mock => mock.SomeIndexedProperty[3] = 25);

SomeIndexedProperty[3]设置为25以来单位测试通过,否则将失败。

答案 1 :(得分:5)

使用Moq 3.1.416.3

安装程序不适用于索引器(因为它需要一个表达式,这意味着赋值语句被排除)

所以你需要使用像

这样的SetupSet
_settingsStore.SetupSet(store => store["MruNotes"] = It.IsAny<string>())
                .Callback<string,string>( (key, value) => persistedValue = value);

一个小警告: 如果键是“MruNotes”,则此表达式仅匹配。我无法使用像It.IsAny这样的匹配器作为密钥。

答案 2 :(得分:3)

在您的测试中,您对索引器的getter的唯一设置期望 - 这将始终返回您的数组中的相应值。索引器的行为不像真实的东西。您可以尝试一些方法来修复它:

  1. 您可以检查是否可以存根此索引器。我个人使用RhinoMocks,所以我不知道是否实现了这个

    someClass.SetupProperty(f => f.SomeIndexedProperty);
    
  2. 您也可以尝试模拟setter并使其更改底层数组。我的第一个猜测是尝试这些方面的东西(不保证它会起作用):

    someClass.Setup(o => o.SomeIndexedProperty[It.IsAny<int>()] = It.IsAny<int>())
    .Callback((index, value) => someValues[index] = value);
    
  3. 或者,如果ISomeClass接口足够小,您可以自己创建一个存根实现(将索引器实现为字典,数组等)。