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
Related
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 have a class with static variable
#Data
public final class Code {
private static Map<String, List<String>> codesForType = new HashMap<String, List<String>>() {{
put("code1", Arrays.asList("AVDF", "WREQ", "AWER"));
put("code2", Arrays.asList("SHYT", "DWEA", "XSSS", "AQWE"));
}};
public static List<String> getCodesByType(String type) {
return codesForType.get(type);
}
}
with following api
#GetMapping("/codes")
public Code getCodeForType() {
return new Code();
}
This is giving exception with message No converter found for return value of type: class com.model.Code.
Tried making the member as public but still has the same issue.
It works when I remove static keyword from private static Map<String, List<String>> codesForType
I could be missing a basic understanding of static keyword.
You don't need to create a new object as your methods are static.
you can simply do this :
#GetMapping("/codes")
public List<String> getCodeForType() {
// replace type with something you will receive in your request.
return Code.getCodesByType(type);
}
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 have a Spring Boot application with the following application.yml
Detail_1:
name: X,Y,Z
place: xplace,yplace,zplace
Detail_2:
name: X,Y,Z
place: xplaceanother,yplaceanother,zplaceanother
How can I obtain this map in java:
X {
detail1 :xplace
detail2 :xplaceanother
}
Y {
detail1:yplace,
detail2:yplaceanother
}
Z{
detail1:zplace,
detail2:zplaceanother
}
I have tried the following code :
#Value${detail1.name}
private String names;
#value${detail2.place}
List<Object> Names = Arrays.asList(getNames().split(","));
List<Object> places = Arrays.asList(getPlaces().split(","));
Then I tried to create a map of names and places corresponding to detail 1
similarly I fetched names and places for detail 2
But In this case i end up with 2 maps , one for detail 1 and one for detail 2.
I need to create a single map.
You need to use #ConfigurationProperties annotation
The following URLs provide good examples in both .properties and .yml format:
https://www.mkyong.com/spring-boot/spring-boot-configurationproperties-example/
https://www.baeldung.com/configuration-properties-in-spring-boot
Please update your config like below in application.yml
map:
detail1:
name:X,Y,Z
place:xplace,yplace,zplace
detail2:
name:X,Y,Z
place:xplaceanother,yplaceanother,zplaceanother
and then configure the property as below,
DetailConfig.java
#Component
#ConfigurationProperties(prefix="map")
public class DetailConfig {
private Map<String, Object> detail1;
private Map<String, Object> detail2;
public Map<String, Object> getDetail1() {
return detail1;
}
public void setDetail1(Map<String, Object> detail1) {
this.detail1 = detail1;
}
public Map<String, Object> getDetail2() {
return detail2;
}
public void setDetail2(Map<String, Object> detail2) {
this.detail2 = detail2;
}
}
You can use the following pojo for property;
public class Detail {
private List<String> name;
private List<String> place;
public Map<String, String> getNamePlaceMap() {
return IntStream.range(0, name.size()).boxed()
.collect(Collectors.toMap(i -> name.get(i), i -> place.get(i)));
}
// getters/setters
}
and use the following configuration to get properties into context;
#Configuration
public class Config {
#Bean
#ConfigurationProperties(prefix = "detail-1")
public Detail detailOne() {
return new Detail();
}
#Bean
#ConfigurationProperties(prefix = "detail-2")
public Detail detailTwo() {
return new Detail();
}
}
and autowire them and pass them to the logic where that map is created;
#Service
public class TestService {
#Autowired
private Detail detailOne;
#Autowired
private Detail detailTwo;
public void test() {
System.out.println(createSpecialMap(detailOne, detailTwo));
}
private static Map<String, Map<String, String>> createSpecialMap(Detail detailOne, Detail detailTwo) {
Map<String, Map<String, String>> resultMap = new HashMap<>();
detailOne.getNamePlaceMap().forEach((key, value) -> {
Map<String, String> subMap = resultMap.getOrDefault(key, new HashMap<>());
subMap.put("detail1", value);
resultMap.put(key, subMap);
});
detailTwo.getNamePlaceMap().forEach((key, value) -> {
Map<String, String> subMap = resultMap.getOrDefault(key, new HashMap<>());
subMap.put("detail2", value);
resultMap.put(key, subMap);
});
return resultMap;
}
}
results in;
{
X={detail1=xplace, detail2=xplaceanother},
Y={detail1=yplace, detail2=yplaceanother},
Z={detail1=zplace, detail2=zplaceanother}
}
Or better in readability, using a Letter class;
public class Letter {
private String name;
private String detail1;
private String detail2;
public Letter(String name, String detail1, String detail2) {
this.name = name;
this.detail1 = detail1;
this.detail2 = detail2;
}
// getters/setters
}
doing the following;
private static List<Letter> createList(Detail detailOne, Detail detailTwo) {
List<Letter> resultList = new ArrayList<>();
Map<String, String> detailOneMap = detailOne.getNamePlaceMap();
Map<String, String> detailTwoMap = detailTwo.getNamePlaceMap();
Set<String> keySet = new HashSet<>();
keySet.addAll(detailOneMap.keySet());
keySet.addAll(detailTwoMap.keySet());
return keySet.stream()
.map(key -> new Letter(key, detailOneMap.get(key), detailTwoMap.get(key)))
.collect(Collectors.toList());
}
will result in;
[
Letter{name='X', detail1='xplace', detail2='xplaceanother'},
Letter{name='Y', detail1='yplace', detail2='yplaceanother'},
Letter{name='Z', detail1='zplace', detail2='zplaceanother'}
]
which is a better result than a raw map of map...
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;