Question

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);
Was it helpful?

Solution

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top