I am trying to mock one property of an object
There is a similar question: Returning the result of a method that returns another substitute throws an exception in NSubstitute But the accepted answer is not working for me.
void Main()
{
var obj = Substitute.ForPartsOf<MyObject>();
//WORKS, But I need a partial mock!:
//var obj = Substitute.For<MyObject>();
obj.PropClass.Returns(Substitute.For<PropClass>());
//It's suggestion, Fails, same error:
//var returnValue = Substitute.For<PropClass>();
//obj.PropClass.Returns(returnValue);
//Fails, same error:
//Lazy implementation of *similar question*
//Func<PropClass> hello = () => Substitute.For<PropClass>();
//obj.PropClass.Returns(x => hello());
//Fails, same error:
//I believe what *similar question* suggests
//obj.PropClass.Returns(x => BuildSub());
obj.PropClass.Dump("Value");
}
public class MyObject
{
public MyObject()
{
_propClasses = new List<PropClass>();
}
private readonly IList<PropClass> _propClasses;
public virtual IEnumerable<PropClass> PropClasses { get { return _propClasses; } }
public virtual PropClass PropClass { get { return PropClasses.FirstOrDefault(); } }
}
public class PropClass
{
}
public PropClass BuildSub()
{
return Substitute.For<PropClass>();
}
These fail with the exception:
CouldNotSetReturnDueToTypeMismatchException:
Can not return value of type PropClassProxy_9 for MyObject.get_PropClasses (expected type IEnumerable`1).
Make sure you called Returns() after calling your substitute (for example: mySub.SomeMethod().Returns(value)),
and that you are not configuring other substitutes within Returns() (for example, avoid this: mySub.SomeMethod().Returns(ConfigOtherSub())).
If you substituted for a class rather than an interface, check that the call to your substitute was on a virtual/abstract member.
Return values cannot be configured for non-virtual/non-abstract members.
Correct use:
mySub.SomeMethod().Returns(returnValue);
Potentially problematic use:
mySub.SomeMethod().Returns(ConfigOtherSub());
Instead try:
var returnValue = ConfigOtherSub();
mySub.SomeMethod().Returns(returnValue);
Normally, for synchronous calls, you can just add a . Throws<TException>() after the method you want to mock throwing an exception (or . ThrowsForAnyArgs<TException>() if you don't care about the input arguments).
To set a return value for a method call on a substitute, call the method as normal, then follow it with a call to NSubstitute's Returns() extension method. var calculator = Substitute. For<ICalculator>(); calculator. Add(1, 2).
NSubstitute is a friendly substitute for . NET mocking libraries. It has a simple, succinct syntax to help developers write clearer tests. NSubstitute is designed for Arrange-Act-Assert (AAA) testing and with Test Driven Development (TDD) in mind.
Ok, this is a bit of a tricky one. First, the solution is to stop obj.PropClass
from calling the base implementation:
obj.When(x => { var get = x.PropClass; }).DoNotCallBase();
obj.PropClass.Returns(prop);
Now the explanation. NSubstitute records the calls made on a substitute, and when we call Returns
, it grabs the last call made and tries to configure that to return a specific value.
What's happening when obj.PropClass.Returns(prop)
runs is that the real obj.PropClass
is called, which in turn calls obj.PropClasses
, so NSubstitute now thinks obj.PropClasses
is the last call. The Returns
then tries to return a single PropClass
when PropClasses
expects an IEnumerable<PropClass>
, hence the exception.
The fix above stops obj.PropClass
from calling the base implementation immediately, so the last call does not get replaced with the PropClasses
one and Returns
can work as expected.
Admittedly this is quite awful, and one of the reasons we held out putting partial mocks into NSubstitute for so long. NSub's nice syntax comes at the price of it not always being able to distinguish when the developer is configuring a call from when real code needs to run. Sorry for the confusion.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With