2

I'm trying to test my cache layer with mockito.

I'm using Caffeine as described here

Basically, I have this...

@Service
class Catalog {

  @Autowired
  Db db;

  @Cachable
  public List<Item> getItems() {
    // fetch from db
    db.someDbMethod();
  }
}

@Configuration
@EnableCaching
class CatalogConfig {
  @Bean
  public CacheManager cacheManager() {
    return new CaffeineCacheManager();
  }
  @Bean
  public Db db() {
     return new Db();
  }
}
// properties as in documentation etc

That works perfectly, the method is cached and works fine.

I want to add a test to verify the DB call is invoked only once, I have something like this but it's not working:

public class CatalogTest {

     @Mock
     Db db;

     @InjectMocks
     Catalog catalog;

     // init etc

     @Test
     void cache() {
       catalog.getItems();
       catalog.getItems();
       verify(db, times(1)).someDbMethod(); // fails... expected 1 got 2
     }
     // Some other passing tests below
     @Test
     void getItems() {
       assertNotNull(catalog.getItems()); // passes
     }
}

I've tried several combinations of @Profile/@ActiveProfile, Config/ContextConfiguration etc.

Community
  • 1
  • 1
OscarRyz
  • 196,001
  • 113
  • 385
  • 569

1 Answers1

1

I had this case. I resolve it by partial bean's import and SpringJUnit4ClassRunner: I'll try to write the main idea:

@RunWith(SpringJUnit4ClassRunner.class)
@Import({CaffeineCacheManager.class, Catalog.class})
public class CatalogTest {

@MockBean
private Db db;

@Autowired
private CaffeineCacheManager cache;

@Autowired
private Catalog catalog;

@Test
void cacheTest(){
   when(db.someDbMethod()).thenReturn(....);

   catalog.getItems();
   catalog.getItems();

   verify(db, times(1)).someDbMethod();

   assertTrue(cache.get(SOME_KEY).isPresent());//if you want to check that cache contains your entity
}

}

You will have really cache bean and a chance to check times of call your mock Db and also you can get cache key in your test.

Dmitrii B
  • 2,672
  • 3
  • 5
  • 14
  • Just tried that and in addition to the verification error I get a `java.lang.Exception: No runnable methods` I've been told that I shouldn't really be testing spring cache itself which I agree. Thanks for the answer, it was worth giving it a try. – OscarRyz Feb 19 '21 at 16:52
  • So, in my case, I really wanted to know that my cache and cache evict work correctly:)I'm pretty sure that's necessary, but you can think other, sure) – Dmitrii B Feb 19 '21 at 16:57