'IMap, Hazelcast instance mock in JUnit
I had mocked HazelcastInstance and its IMap. I had to test several methods (add, remove) which are having this IMap object is locked, updated, unlocked in the order. But the Mocked IMap object is showing zero invocation when I try to run the test. Test class is as follows
@RunWith(PowerMockRunner.class)
public class Test {
@Mock
private HazelcastInstance hazelcastInstance;
@Mock
private IMap<Object, Object> imap; // but in actual class instead of Object (K, V)
// we are having Class Names. private IMap<ClassA,ClassB> imap;
private TestClass testClass;
@Mock
private ClassA a;
@Mock
private ClassB b;
@Test
public void testAdd() {
when(hazelcastInstance.getMap(anyString())).thenReturn(imap);
testClass.add(a, b);
verify(imap, times(1)).lock(any()); //supposed to be invoked (1 time). But it is showing as zero interaction
verify(imap, times(1)).unlock(any());
}
}
Class to be Tested is as follows
public class TestClass {
private IMap<ClassA, ClassB> imap = Hazelcast.newHazelcastInstance().getMap("constant);
public void add(final ClassA key, final ClassB value) {
if (key == null) {
return;
}
try {
imap.lock(key);
imap.put(key, value, 3L, TimeUnit.SECONDS);
} finally {
imap.unlock(key);
}
}
}
Solution 1:[1]
In your case, there are two instances of IMAP. The first one is a mock and the second one is a real imap returned by Hazelcast.newHazelcastInstance(). The problem is that the TestClass.add() method uses the real imap, and the verification uses a mock. So it gets a zero of interactions. You need to inject your mock into a TestClass instance using a constructor or a setter.
Sample code of the test
@RunWith(PowerMockRunner.class)
public class Test1 {
@InjectMocks
private TestClass testClass;
@Mock
private IMap<String, Long> imap;
@Test
public void testAdd() {
String key = "a key";
Long value = 123L;
testClass.add(key, value);
verify(imap, times(1)).lock(key);
verify(imap, times(1)).put(eq(key), eq(value), anyLong(), any(TimeUnit.class));
verify(imap, times(1)).unlock(key);
}
}
TestClass after refactoring:
class TestClass {
private IMap<String, Long> imap;
public TestClass(IMap<String, Long> imap) {
this.imap = imap;
}
public void add(final String key, final Long value) {
if (key == null) {
return;
}
try {
imap.lock(key);
imap.put(key, value, 3L, TimeUnit.SECONDS);
} finally {
imap.unlock(key);
}
}
}
Solution 2:[2]
The problem is that you mock
@Mock
private HazelcastInstance hazelcastInstance;
When tested class call
Hazelcast.newHazelcastInstance()
That show of architecture problems in tested class. The best way to inject a map into TestClass - pass in constructor arguments.
public class TestClass {
private final IMap<ClassA, ClassB> imap;
public TestClass(IMap<ClassA, ClassB> imap) {
this.imap = imap;
}
Now you can create instance of TestClass
IMap imap = mock(IMap.class)
testClass = new TestClass(imap)
Solution 3:[3]
create own imap test class and implements method like this
public class HazelcastMap implements IMap
{
private Map map = new HashMap();
@Override
public void putAll(Map m) {
}
@Override
public int size() {
return 0;
}
@Override
public boolean isEmpty() {
return false;
}
@Override
public boolean containsKey(Object key) {
return map.containsKey(key);
}
@Override
public boolean containsValue(Object value) {
return false;
}
@Override
public Object get(Object key) {
return map.get(key);
}
@Override
public Object put(Object key, Object value) {
map.put(key, value);
return value;
}
@Override
public Object remove(Object key) {
return null;
}
@Override
public boolean remove(Object key, Object value) {
return false;
}
@Override
public void removeAll(Predicate predicate) {
}
@Override
public void delete(Object key) {
}
@Override
public void flush() {
}
@Override
public Map getAll(Set keys) {
return map;
}
@Override
public void loadAll(boolean replaceExistingValues) {
}
@Override
public void loadAll(Set keys, boolean replaceExistingValues) {
}
@Override
public void clear() {
}
@Override
public ICompletableFuture getAsync(Object key) {
return null;
}
@Override
public ICompletableFuture putAsync(Object key, Object value) {
return null;
}
@Override
public ICompletableFuture putAsync(Object key, Object value, long ttl, TimeUnit ttlUnit) {
return null;
}
@Override
public ICompletableFuture putAsync(Object key, Object value, long ttl, TimeUnit ttlUnit, long maxIdle,
TimeUnit maxIdleUnit) {
return null;
}
@Override
public ICompletableFuture setAsync(Object key, Object value) {
return null;
}
@Override
public ICompletableFuture setAsync(Object key, Object value, long ttl, TimeUnit ttlUnit) {
return null;
}
@Override
public ICompletableFuture setAsync(Object key, Object value, long ttl, TimeUnit ttlUnit, long maxIdle,
TimeUnit maxIdleUnit) {
return null;
}
@Override
public ICompletableFuture removeAsync(Object key) {
return null;
}
@Override
public boolean tryRemove(Object key, long timeout, TimeUnit timeunit) {
return false;
}
@Override
public boolean tryPut(Object key, Object value, long timeout, TimeUnit timeunit) {
return false;
}
@Override
public Object put(Object key, Object value, long ttl, TimeUnit ttlUnit) {
return null;
}
@Override
public Object put(Object key, Object value, long ttl, TimeUnit ttlUnit, long maxIdle, TimeUnit maxIdleUnit) {
return null;
}
@Override
public void putTransient(Object key, Object value, long ttl, TimeUnit ttlUnit) {
}
@Override
public void putTransient(Object key, Object value, long ttl, TimeUnit ttlUnit, long maxIdle, TimeUnit maxIdleUnit) {
}
@Override
public Object putIfAbsent(Object key, Object value) {
return null;
}
@Override
public Object putIfAbsent(Object key, Object value, long ttl, TimeUnit ttlUnit) {
return null;
}
@Override
public Object putIfAbsent(Object key, Object value, long ttl, TimeUnit ttlUnit, long maxIdle,
TimeUnit maxIdleUnit) {
return null;
}
@Override
public boolean replace(Object key, Object oldValue, Object newValue) {
return false;
}
@Override
public Object replace(Object key, Object value) {
return null;
}
@Override
public void set(Object key, Object value) {
}
@Override
public void set(Object key, Object value, long ttl, TimeUnit ttlUnit) {
}
@Override
public void set(Object key, Object value, long ttl, TimeUnit ttlUnit, long maxIdle, TimeUnit maxIdleUnit) {
}
@Override
public void lock(Object key) {
}
@Override
public void lock(Object key, long leaseTime, TimeUnit timeUnit) {
}
@Override
public boolean isLocked(Object key) {
return false;
}
@Override
public boolean tryLock(Object key) {
return false;
}
@Override
public boolean tryLock(Object key, long time, TimeUnit timeunit) throws InterruptedException {
return false;
}
@Override
public boolean tryLock(Object key, long time, TimeUnit timeunit, long leaseTime, TimeUnit leaseTimeunit)
throws InterruptedException {
return false;
}
@Override
public void unlock(Object key) {
}
@Override
public void forceUnlock(Object key) {
}
@Override
public String addLocalEntryListener(MapListener listener) {
return null;
}
@Override
public String addLocalEntryListener(EntryListener listener) {
return null;
}
@Override
public String addLocalEntryListener(MapListener listener, Predicate predicate, boolean includeValue) {
return null;
}
@Override
public String addLocalEntryListener(EntryListener listener, Predicate predicate, boolean includeValue) {
return null;
}
@Override
public String addLocalEntryListener(MapListener listener, Predicate predicate, Object key, boolean includeValue) {
return null;
}
@Override
public String addLocalEntryListener(EntryListener listener, Predicate predicate, Object key, boolean includeValue) {
return null;
}
@Override
public String addInterceptor(MapInterceptor interceptor) {
return null;
}
@Override
public void removeInterceptor(String id) {
}
@Override
public String addEntryListener(MapListener listener, boolean includeValue) {
return null;
}
@Override
public String addEntryListener(EntryListener listener, boolean includeValue) {
return null;
}
@Override
public boolean removeEntryListener(String id) {
return false;
}
@Override
public String addPartitionLostListener(MapPartitionLostListener listener) {
return null;
}
@Override
public boolean removePartitionLostListener(String id) {
return false;
}
@Override
public String addEntryListener(MapListener listener, Object key, boolean includeValue) {
return null;
}
@Override
public String addEntryListener(EntryListener listener, Object key, boolean includeValue) {
return null;
}
@Override
public String addEntryListener(MapListener listener, Predicate predicate, boolean includeValue) {
return null;
}
@Override
public String addEntryListener(EntryListener listener, Predicate predicate, boolean includeValue) {
return null;
}
@Override
public String addEntryListener(MapListener listener, Predicate predicate, Object key, boolean includeValue) {
return null;
}
@Override
public String addEntryListener(EntryListener listener, Predicate predicate, Object key, boolean includeValue) {
return null;
}
@Override
public EntryView getEntryView(Object key) {
return null;
}
@Override
public boolean evict(Object key) {
return false;
}
@Override
public void evictAll() {
}
@Override
public Set keySet() {
return null;
}
@Override
public Collection values() {
return null;
}
@Override
public Set entrySet() {
return null;
}
@Override
public Set keySet(Predicate predicate) {
return null;
}
@Override
public Set entrySet(Predicate predicate) {
return null;
}
@Override
public Collection values(Predicate predicate) {
return null;
}
@Override
public Set localKeySet() {
return null;
}
@Override
public Set localKeySet(Predicate predicate) {
return null;
}
@Override
public void addIndex(String attribute, boolean ordered) {
}
@Override
public LocalMapStats getLocalMapStats() {
return null;
}
@Override
public Object executeOnKey(Object key, EntryProcessor entryProcessor) {
return null;
}
@Override
public Map executeOnKeys(Set keys, EntryProcessor entryProcessor) {
return null;
}
@Override
public void submitToKey(Object key, EntryProcessor entryProcessor, ExecutionCallback callback) {
}
@Override
public ICompletableFuture submitToKey(Object key, EntryProcessor entryProcessor) {
return null;
}
@Override
public Map executeOnEntries(EntryProcessor entryProcessor) {
return null;
}
@Override
public Map executeOnEntries(EntryProcessor entryProcessor, Predicate predicate) {
return null;
}
@Override
public QueryCache getQueryCache(String name) {
return null;
}
@Override
public QueryCache getQueryCache(String name, Predicate predicate, boolean includeValue) {
return null;
}
@Override
public QueryCache getQueryCache(String name, MapListener listener, Predicate predicate, boolean includeValue) {
return null;
}
@Override
public boolean setTtl(Object key, long ttl, TimeUnit timeunit) {
return false;
}
@Override
public Object aggregate(Supplier supplier, Aggregation aggregation, JobTracker jobTracker) {
return null;
}
@Override
public Object aggregate(Supplier supplier, Aggregation aggregation) {
return null;
}
@Override
public Collection project(Projection projection, Predicate predicate) {
return null;
}
@Override
public Collection project(Projection projection) {
return null;
}
@Override
public Object aggregate(Aggregator aggregator, Predicate predicate) {
return null;
}
@Override
public Object aggregate(Aggregator aggregator) {
return null;
}
@Override
public String getPartitionKey() {
return null;
}
@Override
public String getName() {
return null;
}
@Override
public String getServiceName() {
return null;
}
@Override
public void destroy() {
}
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | James Graham |
| Solution 2 | Anton Kislitsyn |
| Solution 3 | neoerol |
