Search code examples
c#unit-testingnsubstitute

How to mock indexer return value with Any string key in NSubstitute?


I have a get-only indexer defined on an interface

public interface ISomeInterface
{
  string this[string key] { get; }
}

In a Unit Test with Moq it is valid for any string parameter as the indexer key:

Mock<ISomeInterface> mock = new();
mock
  .Setup(m => m[It.IsAny<string>()]) // <-- valid
  .Returns("anything for all string key");

Unfortunately in NSubstitute the similar seems not possible:

ISomeInterface mock = Substitute.For<ISomeInterface>();
mock[Arg.Any<string>()] // <-- not invalid -> see the update
  .Returns("anything for all string key");

I know that it is possible to setup the mock indexer for a specific key like in this thread:
How to mock object's indexer with private setter in NSubstitute?

How could I setup the mock indexer Return value for Any key input parameter in NSubtitute?

Update:
The indexer mocking (as well) working like a charm in NSubstitute.
My mistake was sourced from that, on the original (derived) interface I had LocalizedString as return value, via a generic localizer, also strict expression return value usage checking is turned on and the error messages had not been fully clear within one line, but here I has tried to simplify my problem in my question as much as possible.
Finally I got back to this code part after days and it turned out (luckily) it is absolutely solvable with NSubstitute. Here is a clarified, more close code sample to the reality for reference:

public interface ISomeInterface
{
  LocalizedString this[string key] { get; }
}

//...

ISomeInterface<LocalizatorType> mock = Substitute.For<ISomeInterface<LocalizatorType>>();

_ = mock[Arg.Any<string>()] // <-- yep, it is working
  .Returns(argsFromCall => new LocalizedString(argsFromCall.ArgAt<string>(0), "en"));

Solution

  • Using mock[Arg.Any<string>()] works as expected:

    [Test]
    public void IndexerSubTest()
    {
        ISomeInterface mock = Substitute.For<ISomeInterface>();
        mock[Arg.Any<string>()]
            .Returns("anything for all string key");
        Assert.That(mock["qq"], Is.EqualTo("anything for all string key"));
    }
    

    Demo @dotnetfiddle.net