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

我无法弄清楚如何使用Moq在C#中设置索引器 。 Moq文档很薄弱,我已经做了很多搜索……我想做的事情在如何设置索引属性的解决方案中类似:

var someClass = new Mock(); 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(); someClass.Setup(o => o.SomeIndexedProperty[It.IsAny()]) .Returns(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]); 

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

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

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

unit testing通过,因为SomeIndexedProperty[3]设置为25,否则将失败。

使用Moq 3.1.416.3

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

所以你需要像使用SetupSet一样

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

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

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

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

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

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