2012-05-24 29 views
7

Tôi đang phát triển một chức năng bộ nhớ cache đơn giản với EhCache. Có một lớp cơ sở chung mà thực hiện giao diện bộ nhớ cache của tôi (BECache):Mocking net.sf.ehcache.Cache (ehcache) bằng phương thức .put (Mockito)

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); 
} 

Mục đích là để có bộ nhớ đệm được xác định như sau:

public class ObjectCache extends EhCacheBase<String, Object>{ 

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

giả 'cacheName' được định nghĩa trong ehcache.xml Tôi nhận được một lớp học tuyệt vời cho lưu vào bộ nhớ cache các đối tượng nhất định.

Tôi đang cố gắng để viết một bài kiểm tra cho 'EhCacheBase.cache (...)' phương pháp đảm bảo một bộ nhớ cache được lấy ra và một giá trị được đặt (sử dụng 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)); 
} 

Khi Tôi chạy thử nghiệm tôi nhận được:

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) 

Có vẻ như phương pháp 'đặt' trong 'bộ nhớ cache' giả gọi một số phương pháp khác. Nhưng như bạn có thể đọc trong tài liệu Mockito:

Sử dụng doNothing() để đặt phương thức void để không làm gì cả. Hãy coi chừng rằng các phương thức void trên mocks không làm gì theo mặc định! Tuy nhiên, có một số trường hợp hiếm khi doNothing() có ích:

Nhân tiện, tôi đã thử: doNothing(). When (cache) .put (bất kỳ (Element.class)); và cũng không giúp được gì.

Bất kỳ ý tưởng gì đang xảy ra?

+0

Bởi vì đặt (Element) là cuối cùng, chế giễu nó là một vấn đề. – Zlatko

Trả lời

8

Cache.put là cuối cùng, vì vậy bạn cần sử dụng PowerMock nếu bạn muốn thử.

thử nghiệm của bạn sẽ trông như thế này:

@RunWith(PowerMockRunner.class) 
@PrepareForTest(Cache.class) 
public class EhCacheBaseTest { 
    private static final String CACHE_NAME = "testCache"; 
    private CacheManager cacheManager; 
    private Cache cache; 
    private EhCacheBase<String, Object> ehCacheBase; 

    @Before 
    public void init() { 
     // You can statically import mock method, but left it this way 
     // for clarity 
     cacheManager = PowerMockito.mock(CacheManager.class); 
     cache = PowerMockito.mock(Cache.class); 
     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)); 
    } 
} 
3

Tôi đã đăng câu hỏi tương tự cho Nhóm Google Mockito (here). Tôi nhận được phản hồi nhanh từ Eric Lefevre-Ardant đã giải thích mọi thứ. Phương thức net.sf.ehcache.Cache.put là phương thức cuối cùng, do đó nó không thể được stubbed - Mockito không cung cấp khả năng thực hiện riêng của nó.

+0

Nếu nó là cuối cùng, bạn có thể thử nó với PowerMock, một phần mở rộng cho Mockito. –

2

Phiên bản mới nhất của Mockito (1.10.19) là not supported by PowerMock.

Thay vì sử dụng PowerMock, nếu có thể, giải pháp khác là mã hóa tới giao diện net.sf.ehcache.Ehcache thay vì triển khai net.sf.ehcache.Cache.

Giao diện Ehcache có thể dễ dàng được mô phỏng với Mockito chuẩn.

Tôi đã thích nghi dụ câu trả lời chấp nhận của:

@RunWith(MockitoJUnitRunner.class) 
public class EhCacheBaseTest { 
    private static final String CACHE_NAME = "testCache"; 

    @Mock private Ehcache cache; 
    @Mock private CacheManager cacheManager; 

    private EhCacheBase<String, Object> ehCacheBase; 

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

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

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

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

Tôi điều này phải là câu trả lời đúng – spekdrum

Các vấn đề liên quan