Question

I'm testing an MVC controller which relies on a value returned from a read-only property on the base class.

The getter for this property throws an exception when it is called as it is relies on a HttpContext (and other nasty stuff) which I would rather avoid mocking.

This is what I've tried so far:

controller = Substitute.ForPartsOf<MyController>(
    Substitute.For<SomeDependency>(),
);

controller.UserInfo.Returns(new UserInfo());

Yet this throws an exception as soon as UserInfo is accessed.

Property on base class is:

public UserInfo UserInfo
{
    get
    {
        // HttpContext dependent stuff
    }
}

I've tried setting the base class property to virtual but then I get a Castle proxy exception.

Was it helpful?

Solution

I think you may be having another problem. NSubstitute is capable of handling substitution of virtual properties. Here is a small program that illustrates

public class SubstitutedClass
{
    public virtual int SubstitutedProperty { get { throw new InvalidOperationException(); }  }
}

internal class Program
{
    private static void Main(string[] args)
    {
        var test2 = Substitute.For<SubstitutedClass>();
        test2.SubstitutedProperty.Returns(10);
        Console.WriteLine(test2.SubstitutedProperty);
    }
}

EDIT: Regarding your use of ForPartsOf I don't think it is possible to override a property this way, since there is no way of informing NSubstitute that we don't want it to call the base code. That's why the documentation mentions that partial sub are not recommended

You could change the base class in order to return the value of a virtual function; this virtual function would then be substituted. No signature change for the callers. Although this is a hack you would get what you need

public class SubstitutedClass
{
    public virtual int SubstitutedProperty { get { return InnerValue(); } }
    public virtual int InnerValue() { throw new InvalidOperationException(); }
}

var test2 = Substitute.ForPartsOf<SubstitutedClass>();
test2.When(t => t.InnerValue()).DoNotCallBase();
test2.InnerValue().Returns(10);
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top