Ответ 1
Если вы хотите протестировать технический аспект, такой как кеширование, вообще не используйте базу данных. Важно понять, что вы хотели бы проверить здесь. Вы хотите убедиться, что для вызова с помощью тех же самых аргументов исключается вызов метода. Репозиторий, выходящий из базы данных, является полностью ортогональным аспектом этой темы.
Вот что я бы рекомендовал:
- Настройте тест интеграции, который настраивает декларативное кэширование (или импортирует необходимый бит и фрагменты из вашей производственной конфигурации.
- Настройте экземпляр mock вашего репозитория.
- Напишите тестовый пример для настройки ожидаемого поведения макета, вызовите методы и проверьте результат соответственно.
Пример
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
public class CachingIntegrationTest {
// Your repository interface
interface MyRepo extends Repository<Object, Long> {
@Cacheable("sample")
Object findByEmail(String email);
}
@Configuration
@EnableCaching
static class Config {
// Simulating your caching configuration
@Bean
CacheManager cacheManager() {
return new ConcurrentMapCacheManager("sample");
}
// A repository mock instead of the real proxy
@Bean
MyRepo myRepo() {
return Mockito.mock(MyRepo.class);
}
}
@Autowired CacheManager manager;
@Autowired MyRepo repo;
@Test
public void methodInvocationShouldBeCached() {
Object first = new Object();
Object second = new Object();
// Set up the mock to return *different* objects for the first and second call
Mockito.when(repo.findByEmail(Mockito.any(String.class))).thenReturn(first, second);
// First invocation returns object returned by the method
Object result = repo.findByEmail("foo");
assertThat(result, is(first));
// Second invocation should return cached value, *not* second (as set up above)
result = repo.findByEmail("foo");
assertThat(result, is(first));
// Verify repository method was invoked once
Mockito.verify(repo, Mockito.times(1)).findByEmail("foo");
assertThat(manager.getCache("sample").get("foo"), is(notNullValue()));
// Third invocation with different key is triggers the second invocation of the repo method
result = repo.findByEmail("bar");
assertThat(result, is(second));
}
}
Как вы можете видеть, здесь мы немного переутомляем:
- Самая важная проверка, я думаю, что второй вызов возвращает первый объект. Это то, что все кэширование. Первые два вызова с одним и тем же ключом возвращают один и тот же объект, тогда как третий вызов с другим ключом приводит к второму действительному вызову в репозитории.
- Мы усиливаем тестовый пример, проверяя, что кеш имеет значение для первого ключа. Можно даже расширить это, чтобы проверить фактическое значение. С другой стороны, я также считаю, что это нормально, чтобы избежать этого, поскольку вы склонны тестировать больше внутренних компонентов механизма, а не поведение на уровне приложений.
Прицепы для ключей
- Вам не нужна инфраструктура для проверки поведения контейнера.
- Настройка тестового окна проста и проста.
- Хорошо разработанные компоненты позволяют писать простые тестовые примеры и требуют меньше усилий для тестирования интеграции.