Моделирование net.sf.ehcache.Cache (ehcache) с помощью заглушки метода .put (Mockito)

Я разрабатываю простую функциональность кэширования с помощью EhCache. Существует общий базовый класс, который реализует мой интерфейс кэширования (BECache):

public class EhCacheBase<K, V> implements BECache<K, V> {

private static CacheManager cacheManager;
private String cacheName;

public EhCacheBase(String cacheName) {
    this.cacheName = cacheName;
}

public void cache(K key, V value) {
    Cache cache = cacheManager.getCache(cacheName);
    if (cache == null) {
        throw new NullPointerException("Failed to obtain cache: " + cacheName);
    }
    Element element = new Element(key, value);
    cache.put(element);
}

Цель состоит в том, чтобы кэши были определены следующим образом:

public class ObjectCache extends EhCacheBase<String, Object>{

    public ObjectCache (String cacheName) {
       super(cacheName);
    }
}

предполагая, что 'cacheName' определено в ehcache.xml, я получаю хороший класс для кэширование определенных объектов.

Я пытаюсь написать тест для метода 'EhCacheBase.cache(...)', который гарантирует извлекается кеш и помещается значение (с помощью Mockito):

private static final String CACHE_NAME = "testCache";
@Mock
private CacheManager cacheManager;
@Mock
private Cache cache;
private EhCacheBase<String, Object> ehCacheBase;

@Before
public void init() {
    MockitoAnnotations.initMocks(this);
    ehCacheBase = new EhCacheBase<String, Object>(CACHE_NAME);
    EhCacheBase.setCacheManager(cacheManager);
}

@Test
public void shouldRetrieveCacheAndPutOneValueInIt() {
    //given
    Object o = new Object();
    when(cacheManager.getCache(CACHE_NAME)).thenReturn(cache);

    //when
    ehCacheBase.cache("KEY", o);

    //then
    verify(cacheManager, times(1)).getCache(CACHE_NAME);
    verify(cache, times(1)).put(any(Element.class));
}

Когда я запускаю тест, я получаю:

java.lang.NullPointerException
    at net.sf.ehcache.Cache.checkStatus(Cache.java:2731)
    at net.sf.ehcache.Cache.putInternal(Cache.java:1440)
    at net.sf.ehcache.Cache.put(Cache.java:1417)
    at net.sf.ehcache.Cache.put(Cache.java:1382)
    at org.fxoo.bookingengine.dao.dataproviders.caches.EhCacheBase.cache(EhCacheBase.java:24)
    at org.fxoo.bookingengine.dao.dataproviders.caches.EhCacheBaseTest.shouldCacheOneValue(EhCacheBaseTest.java:41)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:45)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:42)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:263)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:68)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:47)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:231)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:50)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:300)
    at org.apache.maven.surefire.junit4.JUnit4TestSet.execute(JUnit4TestSet.java:35)
    at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:115)
    at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:97)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.apache.maven.surefire.booter.ProviderFactory$ClassLoaderProxy.invoke(ProviderFactory.java:103)
    at $Proxy0.invoke(Unknown Source)
    at org.apache.maven.surefire.booter.SurefireStarter.invokeProvider(SurefireStarter.java:150)
    at org.apache.maven.surefire.booter.SurefireStarter.runSuitesInProcess(SurefireStarter.java:91)
    at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:69)

Похоже, что метод «поместить» в макете «кэш» вызывает некоторые другие методы. Но, как вы можете прочитать в документации Mockito:

Используйте doNothing() для установки пустых методов, чтобы ничего не делать. Остерегайтесь, что методы void в моках по умолчанию ничего не делают! Однако бывают редкие ситуации, когда doNothing() оказывается кстати:

Кстати, пробовал: doNothing().when(cache).put(any(Element.class)); и это тоже не помогло.

Есть идеи, что происходит?

7
задан jhericks 25 May 2012 в 16:37
поделиться