Using Moq to set indexers in C#

ⅰ亾dé卋堺 提交于 2019-12-18 04:31:45

问题


I'm having trouble figuring out how to set indexers in C# with Moq. The Moq documentation is weak, and I've done a lot of searching... what I'd like to do is similar in the solution to How to Moq Setting an Indexed property:

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

I want to modify the above to work for any index and any value so I can just do something like this:

someClass.Object.SomeIndexedProperty[1] = 5;

Currently I have the following, which works great for the indexed property getter, but if I ever set the value Moq ignores it:

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]);

回答1:


I found a solution to my problem. It requires a shift in my thinking... I had been looking to use NUnit's Assert to verify that the indexer setter in my someClass mock was being called with the correct value.

It seems that with Moq the supported way to do this is to use the VerifySet function. A contrived example:

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

The unit test passes since SomeIndexedProperty[3] is set to 25, but would fail otherwise.




回答2:


Using Moq 3.1.416.3

Setup won't work for indexers (because it takes an expression which means assignment statements are ruled out)

so you need to use SetupSet like

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

A small caveat: this expression only matches if the key is "MruNotes". I was not able to use a matcher like It.IsAny for the key.




回答3:


In your test your only set expectations for the getter of the indexer - and this will always return the corresponding value from your array. The indexer doesn't behave like a real thing. You can try a few things to have it fixed:

  1. You can check if you can stub this indexer. I am personally using RhinoMocks, so I have no idea if this is implemented

    someClass.SetupProperty(f => f.SomeIndexedProperty);
    
  2. You can try to mock the setter as well and make it to change the underlying array. My first guess would be to try something along these lines (no guarantee it will work):

    someClass.Setup(o => o.SomeIndexedProperty[It.IsAny<int>()] = It.IsAny<int>())
    .Callback((index, value) => someValues[index] = value);
    
  3. Or if the ISomeClass interface is small enough, you could just created a stub implementation yourself (that would have the indexer implemented as a dictionary, array etc.)

 



来源:https://stackoverflow.com/questions/2916348/using-moq-to-set-indexers-in-c-sharp

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!