I am new to JMockit. I have recently tried writing unit tests where I have to test a system method that takes an argument. Inside the method under test the argument instance chains multiple of its methods to return a Collection object.
The code below simulates the exact situation I am facing. I am using jmockit-1.9
The system under test
public class SystemUnderTest {
public void doSomething(Dependency dependency) {
List<String> list = dependency.getMap().get("some-key");
System.out.println("got list -> " + list);
}
}
Dependency class
public class Dependency {
private Map<String, List<String>> map;
public Map<String, List<String>> getMap() {
return map;
}
public void setMap(Map<String, List<String>> map) {
this.map = map;
}
}
Test
#Test
public void testDoSomething(
#Mocked Dependency dependency,
#Mocked Map<String, List<String>> map,
#Mocked List<String> list
) {
new NonStrictExpectations() {{
dependency.getMap(); result = map;
map.get(anyString); result = list; //exception occurs here
}};
SystemUnderTest sut = new SystemUnderTest();
sut.doSomething(dependency);
}
When I run the test, I get the following exception
java.lang.IllegalArgumentException: Invalid return value for method returning class java.util.HashMap
at this line
map.get(anyString); result = list;
As it can be clearly see, the return type of map.get() should be a List but it says that the method is returning a HashMap.
What am I doing wrong?
Any help would be appreciated;
Related
I have a class:
public final class Core {
private final Deque<Double> stack = new ArrayDeque<>();
private final HashMap<String, Double> values = new HashMap<>();
public Deque<Double> getStack() {
return stack;
}
public HashMap<String, Double> getValues() {
return values;
}
}
I need a Junit test for this getters, but I don't know how to write it correctly
You get each property and add something to their collection
Then get each property again and verify that what you added is still there
I have a class which has a method I want to test, but it calls a private method in the same class to get a Map value. I want to mock what the private method returns to the method I want to test.
import java.util.*;
public class ClassOne {
public List<String> getList(String exampleString) {
List<String> exampleList = null;
Map<String, String> exampleMap = getMap();
String exampleValue = exampleMap.get(exampleString);
// Does some stuff
exampleList = Arrays.asList(exampleValue.split(","));
return exampleList;
}
private Map<String, String> getMap(){
Map<String, String> exampleMap = new HashMap<>();
exampleMap.put("pre-defined String", "pre-defined String");
return exampleMap;
}
}
From what I can find- it seems like I want to use PowerMock, but I can't seem to figure it out.
A way to mock the return of the private method getMap() when it is called by the method getList.
You should be able to mock it using powermock
"Mocking of Private Methods Using PowerMock | Baeldung" https://www.baeldung.com/powermock-private-method
You will be able to return a call from private method provided its in the same class where the private method is
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.
I'm creating the processor to collect data and provide them in list. But when I'm trying to create test for my method i'm catching assertionerror. What am I doing wrong?
My Class:
#AllArgsConstructor
public class ZteProcessor implements OurProcessor {
private final static String VENDOR = "ZTE";
private String jsonString;
private Map<String, String> metricsGU;
private Map<String, String> metricsUMTS;
private Map<String, String> metricsLTE;
#Override
public List<TimingAdvance> getTA() throws ParseException, NotFoundPatternOrMetricsException {
TimeAdvanceDataStore data = new TimeAdvanceDataStore();
AllDataFromJSONFile fromJSONFile = ProcessorUtil.getAllData(jsonString);
if (jsonString.contains("String")) {
return data.allDataToTimingAdvance(VENDOR, fromJSONFile, metricsGU, 2);
} else if (jsonString.contains("String-2")) {
return data.allDataToTimingAdvance(VENDOR, fromJSONFile, metricsUMTS, 3);
} else if (jsonString.contains("String3")) {
return data.allDataToTimingAdvance(VENDOR, fromJSONFile, metricsLTE, 4);
} else {
throw new NotFoundPatternOrMetricsException();
}
}
}
My Test:
#RunWith(PowerMockRunner.class)
#PrepareForTest({ProcessorUtil.class})
public class ZteProcessorTest {
#Mock
private AllDataFromJSONFile fromJSONFile;
#Mock
private TimeAdvanceDataStore data;
private OurProcessor processor;
private TimingAdvance timingAdvance = new TimingAdvance();
private Map<String, String> metricsGU = new HashMap<>();
private Map<String, String> metricsUMTS = new HashMap<>();
private Map<String, String> metricsLTE = new HashMap<>();
#Test
public void getTATest() throws Exception {
String jsonString = " { String : value}";
processor = new ZteProcessor(jsonString, metricsGU, metricsUMTS, metricsLTE);
List<TimingAdvance> list = new ArrayList<>();
list.add(timingAdvance);
PowerMockito.mockStatic(ProcessorUtil.class);
when(ProcessorUtil.getAllData(jsonString)).thenReturn(fromJSONFile);
when(data.allDataToTimingAdvance(jsonString, fromJSONFile, metricsGU, 2)).thenReturn(list);
assertEquals(list, processor.getTA());
}
}
Stacktrace:
java.lang.AssertionError:
Expected :[TimingAdvance{filial='null', vendor='null', cellName='null', periodDate=null, taMetrics=null}]
Actual :[]
<Click to see difference>
at org.junit.Assert.fail(Assert.java:88)
at org.junit.Assert.failNotEquals(Assert.java:834)
at org.junit.Assert.assertEquals(Assert.java:118)
at org.junit.Assert.assertEquals(Assert.java:144)
My ZteProcessor using static method getAllData(jsonString) of class ProcessorUtill. And for it I use powermock.
The problem stems from the fact that you are setting your expectations on a TimeAdvanceDataStore data mock, but you are creating a new instance of TimeAdvanceDataStore in your method under test.
Since you are already using PowerMockito, you can tap into new object creation like
PowerMockito.whenNew(TimeAdvanceDataStore.class)
.withAnyArguments().thenReturn(data);
On top of that, think how many ZTEProcessors and TimeAdvanceDataStores you have in your app. Do you always want a new instance of TimeAdvanceDataStore in each call to getTA?
If not, just pass TimeAdvanceDataStore in a constructor.
If yes, common approaches when PowerMockito is not at your disposal are:
passing a factory of TimeAdvanceDataStore to ZTEProcessor constructor
passing TimeAdvanceDataStore to getTA method
extracting a method constructing TimeAdvanceDataStore and overriding it in test
I am trying to unit test a method getFruitItemMap() which calls another method getAllItemsBelongingToFruit whose return type is Iterator in the same class. I am trying to mock this method using Mockito.spy(), but unsure of how to return an Iterator. I checked other answers on stack overflow here, but looks like I am missing something here.
class FruitItemImpl {
Map<String, Fruit> getFruitItemMap() {
Map<String, Fruit> fruitMap = new HashMap<>();
Iterator<Fruit> items = getAllItemsBelongingToFruit("Apple");
while (items.hasNext()) {
Fruit fruitItem = items.next();
fruitMap.put(fruitItem.getID(), fruitItem);
}
return fruitMap;
}
public Iterator<Fruit> getAllItemsBelongingToFruit(String fruit) {
//some logic that returns an iterator
}
Here is the unit test:
#Test
public void testGetFruitItemMap() {
Map<String, Fruit> fruitItemMap = new HashMap<>();
FruitItemImpl doa1 = Mockito.spy(dao);
Mockito.doReturn(**new Iterator<Fruit>**).when(doa1).getAllItemsBelongingToFruit("Apple") //Here
Assert.assertEquals(fruitItemMap.size(), doa1.getFruitItemMap().size());
}
Since I am new to Mockito and Unit Testing world, trying to get my head around it. I am not sure how to make mockito return an iterator Mockito.doReturn() in this case.
The easiest way would be to have a collection of the appropriate Fruit objects, and return an Iterator from it. In your case, you could just return an iterator from the fruitItemMap's values() you're using in your test:
#Test
public void testGetFruitItemMap() {
Map<String, Fruit> fruitItemMap = new HashMap<>();
FruitItemImpl doa1 = Mockito.spy(dao);
Mockito.doReturn(fruitItemMap.values().iterator()) // Here!
.when(doa1).getAllItemsBelongingToApple("Apple");
Assert.assertEquals(fruitItemMap.size(), doa1.getFruitItemMap().size());
}