How to test ehcache using mockito?

sphinks picture sphinks · Apr 12, 2013 · Viewed 9.8k times · Source

Im helper method use ehcache, to reduce queries to Db. Now want to implement JUnit+Mockito test to ensure that ehcache works properly. Have such variant of test:

@Autowired
private DBService service;
@Autowired
private DiscountHelper discountHelper;

@Autowired
private CacheManager cacheManager;

@Before
public void setUp() throws Exception {
    assertNotNull(cacheManager);
}

@Test
public void testGetDiscountWithCache() throws RuntimeException,
        InterruptedException {

    String id1 = "id1";
    String id2 = "id2";
    String id3 = "id3";

    List<String> discountsId = new ArrayList<String>();
    discountsId.add(id1);
    discountsId.add(id2);
    discountsId.add(id3);

    List<Map<String, Object>> attrList = new ArrayList<Map<String, Object>>();
    attrList.add(new Discount().getAttributes());
    attrList.add(new Discount().getAttributes());
    attrList.add(new Discount().getAttributes());

    Cache cache = cacheManager.getCache(DiscountHelper.CACHE_NAME);

    assertNotNull(cache);
    assertEquals(0, cache.getSize());

    // First run with empty cache
    when(service.getAllItems(eq(Discount.TABLE_NAME))).thenReturn(attrList);
    List<Discount> actualResult = discountHelper
            .getAllDiscountsUsingCache();
    assertNotNull(actualResult);
    assertEquals(attrList.size(), actualResult.size());
    verify(service).getAllItems(eq(Discount.TABLE_NAME));

    cache = cacheManager.getCache(DiscountHelper.CACHE_NAME);
    // In cache should be 1 record
    assertNotNull(cache);
    assertEquals(1, cache.getSize());

}

And test method is:

@Cacheable(cacheName = CACHE_NAME, refreshInterval = 1000 * 900, decoratedCacheType = DecoratedCacheType.REFRESHING_SELF_POPULATING_CACHE)
public List<Discount> getAllDiscountsUsingCache() throws RuntimeException,
        InterruptedException {
    List<Map<String, Object>> result = dbService
            .getAllItems(Discount.TABLE_NAME);
    List<Discount> discountList = new ArrayList<Discount>();
    for (Map<String, Object> entry : result) {
        discountList.add(new Discount(entry));
    }
    return discountList;
}

And this perfectly works. In test i`m sure that after invocation of method I get something in cache. As you can see I also verify that was called method getAllItems in db service. That is good for first time invocation. Next I add second invocation of discountHelper.getAllDiscountsUsingCache() in the same test like this:

when(service.getAllItems(eq(Discount.TABLE_NAME))).thenReturn(attrList);
actualResult = discountHelper
            .getAllDiscountsUsingCache();
assertNotNull(actualResult);
assertEquals(attrList.size(), actualResult.size());
verify(service, times(0)).getAllItems(eq(Discount.TABLE_NAME));

So I just want to check that on second invocation there will not be calls to DB service via method getAllItems by this verify: verify(service, times(0)).getAllItems(eq(Discount.TABLE_NAME)); and result will be obtain from cache.

But it doesn't work, I still get invocation of DB method. I find this tutorial http://blog.goyello.com/2010/07/29/quick-start-with-ehcache-annotations-for-spring/ and try variant with delegate object for ehcache testing, but it still invoke db methods on test. What`s wrong? By the way in production ehcache works good as I see in logs of tomcat, so this is a problem of test. Any suggestions how to fix it?

Answer

Marcin Zajączkowski picture Marcin Zajączkowski · Apr 14, 2013

In the second invocation you use the same mock object (service) created (as I assume from a question's tag) by Springockito during the Spring context initialization. The mock remembers getAllItems() call from the first invocation. You can:

  • reset the mock before the second invocation using reset(service),

or

  • check after the second invocation) if there is still one (not two) getAllItems() invocation.