Problem
I have to simulate a non-virtual method that returns a bool type in a unit test.
public class XmlCupboardAccess
{
public bool IsDataEntityInXmlCupboard(string dataId,
out string nameInCupboard,
out string refTypeInCupboard,
string nameTemplate = null)
{
return IsDataEntityInXmlCupboard(_theDb, dataId, out nameInCupboard, out refTypeInCupboard, nameTemplate);
}
}
So I have an XmlCupboardAccess mock object, and I’m trying to set up a mock for this method in my test case as seen below.
[TestMethod]
Public void Test()
{
private string temp1;
private string temp2;
private Mock<XmlCupboardAccess> _xmlCupboardAccess = new Mock<XmlCupboardAccess>();
_xmlCupboardAccess.Setup(x => x.IsDataEntityInXmlCupboard(It.IsAny<string>(), out temp1, out temp2, It.IsAny<string>())).Returns(false);
//exception is thrown by this line of code
}
However, there is an exception in this sentence.
Invalid setup on a non-virtual (overridable in VB) member:
x => x.IsDataEntityInXmlCupboard(It.IsAny<String>(), .temp1, .temp2,
It.IsAny<String>())
Is there a way to get around this exception?
Asked by Rahul Lodha
Solution #1
Non-virtual methods and sealed classes are not mockable by Moq. MOQ provides an in-memory proxy type that inherits from your “XmlCupboardAccess” and overrides the behaviors you set out in the “SetUp” function when you run a test using a mock object. In C#, you can only override something if it is designated as virtual, which is not the case in Java. By default, Java considers all non-static methods to be virtual.
Another thing I think you might think about is creating an interface for your “CupboardAccess” and mimicking it instead. It would assist you in decoupling your code and provide long-term benefits.
Finally, frameworks such as TypeMock and JustMock deal directly with the IL, allowing them to mock non-virtual methods. Both, on the other hand, are commercial goods.
Answered by Amol
Solution #2
I unintentionally mistyped the implementation type instead of the interface as an aid to anyone who experienced the same difficulty as me, e.g.
var mockFileBrowser = new Mock<FileBrowser>();
instead of
var mockFileBrowser = new Mock<IFileBrowser>();
Answered by Ralt
Solution #3
Rather than mocking the real class, imitate the class interface. XmlCupboardAccess class’s interface should be extracted.
public interface IXmlCupboardAccess
{
bool IsDataEntityInXmlCupboard(string dataId, out string nameInCupboard, out string refTypeInCupboard, string nameTemplate = null);
}
And instead of
private Mock<XmlCupboardAccess> _xmlCupboardAccess = new Mock<XmlCupboardAccess>();
change to
private Mock<IXmlCupboardAccess> _xmlCupboardAccess = new Mock<IXmlCupboardAccess>();
Answered by Sashus
Solution #4
Please look into it. Why is it necessary for the property I wish to mock to be virtual?
Because Moq produces a proxy class that it uses to intercept calls and deliver your custom values that you placed in the, you may need to construct a wrapper interface or declare the property as virtual/abstract. Call to Returns(x).
Answered by Bryida
Solution #5
If you try to verify that an interface’s extension method is called, you’ll get this error.
If you’re mocking, for example:
var mockValidator = new Mock<IValidator<Foo>>();
mockValidator
.Verify(validator => validator.ValidateAndThrow(foo, null));
Because, you’ll get the same exception. ValidateAndThrow() is an IValidatorT> interface enhancement.
void public static ValidateAndThrowT>(this IValidatorT> validator, T instance, string ruleSet = null, this IValidatorT> validator, this IValidatorT> validator, this IValidatorT> validator, this IValidatorT> validator, this IVa
Answered by Scotty.NET
Post is based on https://stackoverflow.com/questions/21768767/why-am-i-getting-an-exception-with-the-message-invalid-setup-on-a-non-virtual