7

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.

Ben Foster
  • 34,340
  • 40
  • 176
  • 285
  • Can you add a dependency to `MyController` that accesses `UserInfo` and related stuff? At test time pass in a `FakeUserInfoProvider` and at run time use a `HttpContextUserInfoProvider`? – David Tchepak Apr 10 '14 at 02:48

1 Answers1

8

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);
samy
  • 14,832
  • 2
  • 54
  • 82
  • What about the partial mock `ForPartsOf`? – Ben Foster Apr 09 '14 at 11:45
  • @BenFoster Indeed, I hadn't seen the ForPartsOf method, which doesn't work in this case. Looking into it – samy Apr 09 '14 at 12:07
  • @BenFoster edited my answer to add some information regarding `ForPartsOf` – samy Apr 09 '14 at 12:58
  • Thanks, the fact that `ForPartsOf` still executes the original property code was the problem. Since I couldn't change the base class I just ended up mocking `ControllerContext`. – Ben Foster Apr 10 '14 at 09:23