Почему @Cachable(…) работает с @Bean, возвращающим макет (), но не с @MockedBean

#spring-boot #mockito #spring-boot-test #spring-bean #spring-cache

Вопрос:

Почему кэш заполняется значениями при использовании

 @Autowired
ServiceXY serviceXY

@TestConfiguration
static class AppDefCachingTestConfiguration {
    @Bean
    public ServiceXY ServiceXYMock() {
        return mock(ServiceXY.class);
    }
}
 

Но не с

 @MockBean
ServiceXY serviceXY
 

При использовании @MockBean я получаю исключение NullPointerException при доступе к значениям кэша, подобным этому, в моем тесте:

 @Autowired
ConcurrentMapCacheManager cmcm; 

@Test
void anTest(){
when(serviceXY.methodThatFillsCache(anyString()).thenReturn("ABC");

serviceXY.methodThatFillsCache("TEST1");

cmcm.getCache("Cachename").get("TEST1",String.class).equals("ABC");
...
}
 

Ответ №1:

Кэширование реализуется с помощью прокси-сервера, который перехватывает вызовы кэшируемого метода. При использовании @MockBean Spring Boot намеренно отключает проксирование. Одним из следствий этого является то, что кэширование не выполняется. Кто-то недавно отметил, что это не очень хорошо документировано, поэтому мы можем обновить документы в будущем.

Если вы хотите проверить, работает ли кэширование должным образом, вам следует либо использовать подлинную реализацию вашего сервиса, либо создать макет самостоятельно с помощью @Bean метода, как вы сделали в первом примере в своем вопросе.

Комментарии:

1. Спасибо тебе, Энди. Я смотрю в javadoc, это было бы отличное место, чтобы указать на это, или, может быть, я просто наблюдал за этим. Я уже знал, как решить эту проблему, но я хотел понять, что происходит на заднем плане, что сделало ее намного яснее.