When testing code that interacts with lower layers, I often stub out the
lower layer to return objects to the code that I’m actually testing. I
mostly use stubs generated by a mocking framework, but I occasionally
come across cases where the stub needs to do something other than just
return a known object. Take the case of a
DAO that assigns a
generated identifier to a domain object. Here we see a service that
takes a name, creates a User
object with it, persists the object and
returns the generated id to the caller.
public interface UserService {
Long create(String name);
}
In this situation, I would want to test that the following are true.
- the service calls the
persist
method on the DAO - the service returns the correct id value
Testing the DAO call is easy enough using a mock.
@Test
public void create_calls_persist() {
UserDao dao = mock(UserDao.class);
UserService service = new UserServiceImpl(dao);
service.create("bob kelso");
verify(dao).persist(any(User.class));
}
How do we test that the service returns the correct id? The id will be
null by default because it’s a Long
. At the very least we should make
sure it’s a non-null value, and we would prefer to assert that it’s
something specific. We can’t stub the domain object because the service
creates it. One option is to create a stub implementation of the DAO
that simply sets the object’s id to a known value. Assume that our DAO
interface looks like the one below.
public interface UserDao {
void persist(User user);
void update(User user);
void delete(User user);
User load(Long id);
User findByName(String name);
}
While there aren’t too many methods, we really don’t care about anything
but persist
, so it’d be nice if we only had to deal with the things we
do care about. This is where Mockito comes in.
Using the partial mocks
feature added in version 1.8.0, we can create an abstract class that
only implements the persist
method, and let Mockito supply its useful
default implementations for the rest of the methods.
public class UserServiceTest {
public static final Long ONE_OF_TYPE_LONG = 1L;
public static abstract class UserDaoStub implements UserDao {
@Override
public void persist(User user) {
user.setId(ONE_OF_TYPE_LONG);
}
}
}
We now have an abstract stub for our DAO that will set the id of any objects it persists to a 1 of type Long. You can obviously do something more complicated if needed. Next we use Mockito to provide the rest of the implementation.
@Test
public void create_returns_generated_id() {
UserDao dao = mock(UserDaoStub.class);
doCallRealMethod().when(dao).persist(any(User.class));
UserService service = new UserServiceImpl(dao);
Long id = service.create("bob kelso");
assertThat(id, is(ONE_OF_TYPE_LONG));
}
The only thing different about creating a partial mock, is that you need
to call either thenCallRealMethod()
or doCallRealMethod()
to
indicate which method calls to delegate to the real object. The example
above uses doCallRealMethod()
because persist
has a void return
type. I’ve found this technique to be a very effective way to create
focused stubs that allow you to specify what you need to, and not worry
about the rest.
Update 2012-05-31
Someone pointed out in the now gone comments that this approach does not work if the stub class needs to carry state. If this is the case for you, you may want to consider a fake. This may also be an opportunity to refactor your code to make it easier to test the desired behavior in isolation.