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
Mapis mutable, so any code that modifies it will affect the database’s copy. - DAOs have many more methods than
saveandfindByIdand 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. |




