Question

Given I have a controller class as such:

public class ResourceController : AuthorizedController
{      
    public virtual string Resource()
    {
         //do magic
    }

    public virtual string ResourceParent()
    {
        var url = Resource();
        return url;
    }
}

}

With the test harness:

[Subject(typeof (ResourceController))]
public class When_I_want_the_parent_resource : WithSubject<ResourceController>
{
    private static readonly string ParentUrl = "/organizations/1";
    private static readonly string ResourceUrl = "/organizations/1/contacts/1";
    private static string _result;

    private Establish context = () =>
                                    {
                                        The<ResourceController>()
                                            .WhenToldTo(x => x.Resource())
                                            .Return(ResourceUrl);
                                    };

    private Because of = () => _result = Subject.ResourceParent();

    private It should_match_the_expected_parent_url = () =>
                             _result.ShouldEqual(ParentUrl);
}

This unit test will fail because Subject.ResourceParent() will return null because Machine.Fakes has automocked this method. As a temporary workaround I just removed the virtual keyword from ResourceParent to be able to test my code. I assume there has to be a real solution for me to tell Machine.Fakes to not override ResourceParent()

Was it helpful?

Solution

actually there isn't a "real" solution in Machine.Fakes for this. I would argue that you need to reconsider you're fixture design.

First of all, as Tim already pointed out, you you should't fake any methods on the subject itself. Instead you should fake the dependencies of your controller and use your controller as-is in specifications. The intended usage of the "The" method is to access the dependencies of the subject under specification, but what you try in your spec is to access the subject itself. I think that's where things go wrong. The <ResourceController> and subject are actually separate instances. That's why you configured interaction doesn't happen.

Just some options to fix this in your code:

  • Introduce a new dependency in your code which you can stub via "The"
  • If the first seems to heavyweight, you could also replace the virtual method with a Func<string> dependency for your controller and use the "Configure" method to inject a specification specific one for your spec.

HTH,

Bjoern

OTHER TIPS

If you're testing a controller, then perhaps you shouldn't be creating mocks or fakes of that controller. Otherwise you're just testing a mock and the test doesn't really have any validity.

Mock or fake the dependencies of the controller. Test the real controller.

In the end I ended up pulling this test out of Machine.Fakes and put it into a regular unit test. Then I just used Moq directly to configure the HttpRequestBase to seed data I needed and then just manually created my controller class and invoked methods on it.

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