Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature - stubbing indexers #1178

Closed
tonyhallett opened this issue Jun 24, 2021 · 2 comments
Closed

Feature - stubbing indexers #1178

tonyhallett opened this issue Jun 24, 2021 · 2 comments

Comments

@tonyhallett
Copy link
Contributor

Like SetupProperty

@stakx
Copy link
Contributor

stakx commented Jun 30, 2021

I think this capability – that is, a SetupIndexer method for stubbing indexers similar to what SetupProperty does for properties – is missing in Moq with good reason:

Consider auto-implemented properties in C#:

object Property { get; set; } = "initial value";
//              ^^^^^^^^^^^^^

C# will automatically generate an anonymous backing field for that property. SetupProperty corresponds to that syntax and essentially does the same thing:

mock.SetupProperty(m => m.Property, "initial value");

When it comes to indexers, however, C# does not support the auto-implemented variety:

object this[int index, ...] { get; set; }
//                          ^^^^^^^^^^^^^
error CS0501: 'C.this[int].get' must declare a body because it is not marked abstract, extern, or partial
error CS0501: 'C.this[int].set' must declare a body because it is not marked abstract, extern, or partial

(What would that do, anyway? Create a backing Dictionary<,>? Or something altogether different?)

One of the principles behind Moq is that it lets you automate what you would otherwise have to spell out manually. In the same way that SetupProperty mimicks auto-implemented properties, SetupIndexer would likely have to mimick auto-implemented indexers, and since those don't actually exist in C#, I think Moq shouldn't have that capability either.

If we were to introduce SetupIndexer anyway, Moq would let you do something with indexers that you normally couldn't have done anyway, suggesting that SetupIndexer would serve only a relatively rare use case... and it probably wouldn't pay off to have to maintain a new feature for that.

In the few occasions where you would actually need something like a dictionary-like indexer, it's already not too hard to achieve that using the existing methods:

var mock = new Mock<IFoo>();

var dict = new Dictionary<int, object>();
mock.Setup(m => m[It.IsAny<int>()]).Returns((int index) => dict[index]);
mock.SetupSet(m => m[It.IsAny<int>()] = It.IsAny<object>()).Callback((int index, object value) => dict[index] = value);

public interface IFoo
{
    object this[int index] { get; set; }
}

For the reasons laid out above, my personal vote goes against SetupIndexer, I'm not going to review your PR at this time. I'll leave this issue open for a while in case anyone else wants to offer a different perspective.

@tonyhallett
Copy link
Contributor Author

In the few occasions where you would actually need something like a dictionary-like indexer, it's already not too hard to achieve that using the existing methods:

Agreed but this pull request does it for n keys.

Regardless no problem.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants