1

I use Mockito and JUnit 5. I have a small program that counts distinct characters in a string. I have a cache in the form of a Map and the result is picked from the cache if the input string had been processed before. My goal is to write a test using Mockito to verify that the result is picked from the cache if the string had been processed before. I can't figure out how to use the verify Mockito method properly. Here is my code:

public class CounterDecorator implements CharCounter{
    Cache cache;
    CharCounter counter;
    public CounterDecorator(Cache cache, CharCounter counter) {
        this.cache = cache;
        this.counter=counter;
    }

    @Override
    public Map<Character, Integer> count(String text) {
        if(!cache.contains(text)) {
            System.out.println("New entry in cache");
            cache.putText(text, counter.count(text));
        }
        return cache.getText(text);
    }
}


public class Cache {
    private Map <String, Map<Character, Integer>> cache = new HashMap <>();
    
    public void putText(String text, Map <Character, Integer> result) {
        cache.put(text, result);
    }
    
    public Map<Character, Integer> getText(String text) {
        
        return cache.get(text);
    }
    
    public boolean contains(String text) {
        return cache.containsKey(text);
    }
    
}

And tests:

@ExtendWith(MockitoExtension.class)
class DecoratorTest {
    @Mock
    Cache mcache;
    @Mock
    CharCounter mcharcounter;

    @InjectMocks
    CounterDecorator decorator;
    

    @Test
    void testWhenCacheIsNotEmpty() {
        Map<Character, Integer> testMap = Collections.emptyMap();

        verify(mcache, atLeastOnce()).putText("some string", testMap);
    }
}

I am sure I use Mockito wrong. But I can't figure out how to resolve my problem. Thank you in advance.

EDIT. I edited my tests part a bit: removed that confusing map instantiation.

IceTeaGreen
  • 133
  • 12
  • 1
    your test setup is exactly the same for both tests but your assertions are different. I guess that the setup of the second test is wrong, but I don't really inderstand what the integers are for – Arnaud Claudel Sep 27 '20 at 20:29
  • Not sure if I understand your problem correctly. Are you trying to check whether the cached value is used or not? If you are interested in cache metrics refer https://stackoverflow.com/questions/51972607/spring-boot-2-actuator-metrics-cache PS: Mockito is used for unit testing and you are trying to do integration testing. – kulsin Sep 27 '20 at 20:38
  • @kulsin it appears your link is unrelated to this question. They wrote their own `Cache` class and now trying to verify that it works correctly. It is therefore a unit test and has nothing to do with the Spring Boot question you linked. – Marcono1234 Sep 27 '20 at 20:48
  • I edited my tests part. Now it has only one test which should verify that the method responsible for saving data in the cache is called only once. – IceTeaGreen Sep 27 '20 at 20:49
  • Not directly related to the question, but it might be good to use for the test class the name of the tested class + "Test", i.e. `CounterDecoratorTest` instead of `DecoratorTest`. Also performance of `CounterDecorator.count(...)` can be improved by storing `counter.count(...)` result in a local variable in case of cache miss and returning its value instead of performing a second look up to retrieve the value again. – Marcono1234 Sep 27 '20 at 21:33
  • thank you for the tips! – IceTeaGreen Sep 27 '20 at 21:39
  • 2
    now your code never actually executes any code. You forgot to call `decorator` – Arnaud Claudel Sep 27 '20 at 21:42

0 Answers0