'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