Enterprise Java

Spring Data Mock DAO

Warning, the following code example is suitable for a narrow range of use cases… but it’s strangely useful.

When writing tests against Spring services or controllers, we may wish to mock the DAO layer completely. This can be achieved:

@MockBean
private MyDao myDao;

And the mock dao is then wired into our services etc.

However, there are situations where we’re doing something complex in a higher order test, and we want this DAO to function just enough. This is where the following function may help:

/**
 * Turn any integer keyed mock dao into a sort of working one for save and findById
 *
 * @param mockDao the dao to mock
 * @param <T>     the type of element
 */
static <T> void givenFakeSaveAndLoad(CrudRepository<T, Integer> mockDao,
      Function<T, Integer> getId, BiConsumer<T, Integer> setId) {
    Map<Integer, T> fakeDb = new HashMap<>();
    AtomicInteger idGenerator = new AtomicInteger(123);
    given(mockDao.save(any()))
        .willAnswer(answer((T toSave) -> {
            if (getId.apply(toSave) == null) {
                setId.accept(toSave, idGenerator.getAndIncrement());
            }
            fakeDb.put(getId.apply(toSave), toSave);
            return toSave;
        }));

    willAnswer(answer((Integer id) -> Optional.ofNullable(fakeDb.get(id))))
        .given(mockDao)
        .findById(argThat(id -> id >= 123));
}

What this is doing is simulating a really simple database by using a Map. It can operate on any CrudRepository where the key field is an Integer. Technically you could make it operate on other key types if you wanted to. I’m using AtomicInteger as the key generator here, so Integer is all I want.

What this code does is puts a POJO in a Map on save and retrieves it from the Map on findById. There are many ways this is not enough of a mock of a database… but let’s just look at an example of using it:

givenFakeSaveAndLoad(learnerDriverDao,
     LearnerDriver::getId,
     LearnerDriver::setId);

We call it with the DAO we wish to mock and the functions on the POJO that access its ID field. Then it adds this moderately handy map-based DAO.

Why It’s Rubbish

Loads of reasons why this is not a good idea:

  • The POJO stored in the Map is mutable, so any code that modifies it will affect the database’s copy.
  • DAOs have many more methods than save and findById and this doesn’t cover them
  • Tests that rely on stateful mock objects soon get out of hand

Conversely, this is a simple pattern that’s really helped make a few tests easy!

Published on Java Code Geeks with permission by Ashley Frieze, partner at our JCG program. See the original article here: Spring Data Mock DAO

Opinions expressed by Java Code Geeks contributors are their own.

Ashley Frieze

Software developer, stand-up comedian, musician, writer, jolly big cheer-monkey, skeptical thinker, Doctor Who fan, lover of fine sounds
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Inline Feedbacks
View all comments
Back to top button