views:

305

answers:

4

I've got a PresenterFactory that creates Presenter classes based on a Role parameter. Specifically, the Role parameter is an external class which I cannot control (IE 3rd party.)

My factory looks something like this:

public class PresenterFactory {
    public Presenter CreatePresenter(Role role, ...) {
        if (role.IsUserA("Manager")) {
            return new ManagerPresenter(...)
        }
        if (role.IsUserA("Employee")) {
            return new EmployeePresenter(...)
        }
    }
}

I'm stuck on how to write the unit test for this since creating the Role object forces a database access. I thought that I could Mock this object. My test looked like this:

public void TestPresenterFactory()
{
    var mockRole = new Mock<Role>();

    mockRole .Setup(role=> role.IsUserA("Manager"))
        .Returns(true)
        .AtMostOnce();

    PresenterFactory.CreatePresenter(mockRole.Object, ...);

    mockUserInfo.VerifyAll();
}

However I receive an ArguementException:

Invalid setup on a non-overridable member: role=> role.IsUserA("Manager")

I'm not sure where to go and sure could use some course correction. What am I doing wrong?

A: 

What you want to mock is the creation of a Role object, then pass that mock object into your CreatePresenter method. On the mock you would set whatever properties required to determine what kind of user it is. If you still have dependencies on the database at this point, then you might look at refactoring your Role object.

Doug R
That's what I tried, but got an *Invalid setup on a non-overridable member* exception
Gavin Miller
In that case I recommend womp's answer of writing a wrapper class around the Role object.
Doug R
+2  A: 

You can create a wrapper object for Role that has all the same methods and properties, but is mockable, and the default implementation simply returns the underlying Role's implementation.

Then your tests can use the wrapper Role to set up the desired behaviour.

This is often a way to get around concrete classes that really need mocking.

womp
A: 

Consider using a mocking framework that does not impose artificial constraints (such as requirements for methods to be virtual, for classes to not be sealed, etc) on how your code must be written to be mockable. The only example of such that I'm aware of in .NET context is TypeMock.

Pavel Minaev
An expensive solution ;)
womp
A: 

In Java when using EasyMock extensions you would be able to mock "real" objects and methods, most likely there's equivalent or alternative mock framework that you can use for your purpose

DroidIn.net