views:

514

answers:

3

I've use Moq to mock my repositories. However, someone recently said that they prefer to create hard-coded test implementations of their repository interfaces.

What are the pros and cons of each approach?

Edit: clarified meaning of repository with link to Fowler.

A: 

I assume that by "repository" you mean a DAO; if not then this answer won't apply.

Lately I've been making "in memory" "mock" (or test) implementations of my DAO, that basically operate off of data (a List, Map, etc.) passed into the mock's constructor. This way the unit test class is free to throw in whatever data it needs for the test, can change it, etc., without forcing all unit tests operating on the "in memory" DAO to be coded to use the same test data.

One plus that I see in this approach is that if I have a dozen unit tests that need to use the same DAO for their test (to inject into the class under test, for example), I don't need to remember all of the details of the test data each time (as you would if the "mock" was hardcoded) - the unit test creates the test data itself. On the downside, this means each unit test has to spend a few lines creating and wiring up it's test data; but that's a small downside to me.

A code example:

public interface UserDao {
    User getUser(int userid);
    User getUser(String login);
}

public class InMemoryUserDao implements UserDao {

    private List users;

    public InMemoryUserDao(List users) {
        this.users = users;
    }

    public User getUser(int userid) {
        for (Iterator it = users.iterator(); it.hasNext();) {
            User user = (User) it.next();
            if (userid == user.getId()) {
                return user;
            }
        }

        return null;
    }

    public User getUser(String login) {
        for (Iterator it = users.iterator(); it.hasNext();) {
            User user = (User) it.next();
            if (login.equals(user.getLogin())) {
                return user;
            }
        }

        return null;
    }
}
matt b
I mean the repository pattern. I've edited the question with a link to Martin Fowler's definition.
Mike Scott
+4  A: 

I generally see two scenarios with repositories. I ask for something, and I get it, or I ask for something, and it isn't there.

If you are mocking your repository, that means you system under test (SUT) is something that is using your repository. So you generally want to test that your SUT behaves correctly when it is given an object from the repository. And you also want to test that it handles the situation properly when you expect to get something back and don't, or aren't sure if you are going to get something back.

Hard-coded test doubles are ok if you are doing integration testing. Say, you want to save an object, and then get it back. But this is testing the interaction of two objects together, not just the behavior of the SUT. They are two different things. If you start coding fake repositories, you need unit tests for those as well, otherwise you end up basing the success and failure of your code on untested code.

That's my opinion on Mocking vs. Test Doubles.

NerdFury
+3  A: 

SCNR:

"You call yourself a repository? I've seen matchboxes with more capacity!"

Michael Borgwardt
That's the first thing I thought of when I read the question :-)
Ferruccio
Thank you for this response. It saved me the effort.
Mark