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

Invalid setup on non-virtual member. #590

Closed
nathvi opened this issue Feb 22, 2018 · 3 comments
Closed

Invalid setup on non-virtual member. #590

nathvi opened this issue Feb 22, 2018 · 3 comments

Comments

@nathvi
Copy link

nathvi commented Feb 22, 2018

I have an issue, probably just an ignorance of how the API works but here it goes.
I have a non-virtual public method ListHasElements that I'm setting up like so:
var mockConsumerService = new Mock<KeyLoggingConsumerService>(coreConfig); mockConsumerService.Setup(x => x.ListHasElements(listToConsume)).Returns(true);

The second statement is throwing the following error when executed:
Invalid setup on non-virtual (overridable in VB) member: x => x.ListHasElements("listToConsume")

I'm guessing I'm missing something here. Is there is a way to test non-virtual members?
The only way I've seen how to do this is to make the non-virtual member part of an interface. This seems kind of clunky.

@stakx
Copy link
Contributor

stakx commented Feb 22, 2018

I have a non-virtual public method ListHasElementsthat I'm setting up

Non-virtual (or sealed) methods cannot be set up. This is a hard limitation, and there's nothing that can be done about it. (To understand why, briefly stop and think about how you would "set up" this non-virtual method if you wrote the mock class manually, i. e. without a helper library such as Moq... answer: you wouldn't be able to change / override its behavior in any way.)

Either you make that method virtual so it can be overridden, or you use the interface method approach that you've already mentioned.

@stakx stakx closed this as completed Feb 22, 2018
@nathvi
Copy link
Author

nathvi commented Feb 22, 2018

Thank you for your answer. I am curious though, are there any pros/cons that you take into account when choosing to use the interface method vs the virtual method? Adding "virtual" to a method seems a pretty low cost compared to making an interface.

@stakx
Copy link
Contributor

stakx commented Feb 22, 2018

Are there any pros/cons that you take into account when choosing to use the interface method vs the virtual method?

When it comes to testing with Moq, interfaces are fully supported. That is not the case with classes, which can have unsupported constructs such as static, sealed, or non-virtual members. So from a purely Moq point of view, prefer interfaces for testing.

That being said, you shouldn't let "Moq-ability" influence your code design too much. There's always the question of when to prefer interfaces over abstract base classes. You can find a lot of good material and opinions on that particular subject on the web. I'm not certain I can contribute anything better.

That being said, a few points I might typically consider are:

  • As the "baseline" decision, prefer to use interfaces over abstract base classes.

  • How likely is it that I'll have more than one actual implementation of an interface? If that seems unlikely, I might end up foregoing the interface and just writing a sealed class. (That wouldn't be testable using Moq 4, so given that you might want to test code that uses this class, an interface might become necessary so that in test code, the actual implementation can be exchanged for a test double.)

  • If there is likely going to be more than just one single implementation, will each implementation have to do the same basic boilerplate work over and over again? Or does the base type offer some functionality that should always work the same way that cannot be expressed as an extension method? If so, I might end up with an abstract base class.

There's probably a lot more than I forget and the above is grossly oversimplified, so take this with a grain of salt. When it comes to Moq, know that interfaces are better supported while support for mocking classes is more spotty.

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

No branches or pull requests

2 participants