I want to return the value of DAO using mokito but it is not working properly.
It doesn't always work.
As you can see from the code below, it sometimes returns the value I want, but sometimes it doesn't know why.
Below is an example of my code.
Example classes
public Myclass {
#Resource(name=userDao)
UserDao userDao;
#Resource(name=infoDao)
InfoDao infoDao;
public boolean checkUserService(UserVo userVo){
int checkCnt = userDao.getUserCnt(userVo);
InfoVo infoVo = new InfoVo();
infoVo.setUserId(...);
infoVo.set....
....
Map<String,Object> userInfo = infoDao.getInfo(infoVo);
return true or false;
}
}
public UserDao {
public <T> int getUserCnt(T value){
}
}
public InfoDao {
public <T> Map<String,Object> getInfo(T vo){
...
}
}
Test Case
#ExtendWith(MockitoExtension.class)
#RunWith(SpringJUnit4ClassRunner.class)
#WebAppConfiguration
public MyclassTest{
#Mock
UserDao userDao ;
#Mock
InfoDao infoDao ;
#Before
public void setup() {
MockitoAnnotations.initMocks(this);
}
#Test
public testCheckUserService()throws Exception{
UserVo userVo = new UserVo();
when(userDao.getUserCnt(userVo)).thenReturn(1); // This code works normally.
Map<String,Object> checkInfoMap = new HashMap<>();
checkInfoMap.put("name","abc");
InfoVo infoVo = new InfoVo();
//I expected the result to be checkInfoMap, but the empty value will be returned.
when(infoDao.getInfo(infoVo)).thenReturn(checkInfoMap);
//This code likewise always returns an empty value.
when(infoDao.getInfo(anything())).thenReturn(checkInfoMap);
//This code likewise always returns an empty value.
when(infoDao.getInfo(any(InfoVo.class))).thenReturn(checkInfoMap);
}
}
when(userDao.getUserCnt(userVo)).thenReturn(1); This code works, but why doesn't the code below it work?
Related
I have to test DataIdResolver class and it is a class that has a switch case and optional in it. Also there is a one case and default part of switch case that contains each method call. I need to test it and I am not sure how to do it.
public class DataIdResolver {
final DataService dataService;
public DataIdResolver(DataService dataService) {
this.dataService = dataService;
}
public List<String> fetchDataIds(String dataId){
Optional<DataResponse> optionalResponse = dataService.getData(dataId);
if(optionalResponse.isPresent()) {
switch(optionalResponse.get().author){
case "Harry Potter":
return resolveAuthorDataIdAndSiblingsAuthorDataId(optionalResponse.get());
default:
return resolveServerSideDataIdAndSiblingsServerSideDataId(optionalResponse.get());
}
} else {
return List.of(dataId);
}
}
private List<String> resolveAuthorDataIdAndSiblingsAuthorDataId(DataResponse response) {
List<String> resolvedServerSideIds = new ArrayList<>();
resolvedServerSideIds.add(response.serverSideDataId);
if (!response.siblings.isEmpty()){
for (SiblingsDataResponse s : response.siblings) {
resolvedServerSideIds.add(s.dataId);
}
}
return resolvedServerSideIds;
}
}
Here is what I have for start:
public class DataIdResolverTest {
DataService dataService = Mockito.mock(DataService.class);
RestTemplate restTemplate = Mockito.mock(RestTemplate.class);
private final HttpDataService httpDataService = new HttpDataService(restTemplate);
#Test
public void fetchDataIds() {
Optional<DataResponse> optionalResponse = dataService.getData(dataId);
optionalResponse.ifPresent(dataResponse -> Mockito
.when(!dataResponse.siblings.isEmpty()).thenReturn(Boolean.valueOf("siblingsDataId")));
httpDataService.getData("dataIdTest");
}
#Test
public void resolveAuthorDataIdAndSiblingsAuthorDataId(){
}
}
Should I test it all in one test method?
What is the best way to do it?
Any advice appreciated.
Here's example.
public class DataIdResolverTest {
DataService dataService = Mockito.mock(DataService.class);
private final DataIdResolver dataIdResolver = new DataIdResolver(dataService);
#Test
public void fetchDataIds_returnsListWithExceptedString_whenOptionalIsPresent() {
//given
ResponseData responseData = createYourResponseDataHere();
Mockito.when(dataService.getData()).thenReturn(Optional.of(responseData));
//when
List<String> dataIds = dataIdResolver.fetchDataIds();
//then
//here you need to check if your dataIds have expected values, you can use Assertions
//example
Assert.assertEquals("expectedString", dataIds.get(0));
}
#Test
public void fetchDataIds_returnsEmptyList_whenOptionalIsNotPresent() {
//given
ResponseData responseData = createYourResponseDataHere();
Mockito.when(dataService.getData()).thenReturn(Optional.empty());
//when
List<String> dataIds = dataIdResolver.fetchDataIds();
//then
Assert.assertTrue(dataIds.isEmpty());
}
}
In general read more about unit tests. You want test class DataIdResolver but you didn't even create instance of it. You can't test private method without reflection, in general it's bad practice to do it. Also remember to name your test methods better, you can read about it here https://dzone.com/articles/7-popular-unit-test-naming
Below is main code consist of one util class and service class using it
#PropertySource("classpath:atlas-application.properties")
public class ApacheAtlasUtils {
#Value("${atlas.rest.address}")
private String atlasURL;
#Value("${atlas.rest.user}")
private String atlasUsername;
#Value("${atlas.rest.password}")
private String atlasPassword;
private AtlasClientV2 client;
public AtlasClientV2 createClient() {
if (client == null) {
return new AtlasClientV2(new String[] {atlasURL}, new String[] {atlasUsername, atlasPassword});
} else {
return client;
}
}
}
Service Class is below :-
#Override
public Page<SearchResultDto> findFilesWithPages(QueryParent queryParent, Pageable pageable)
throws AtlasServiceException {
// Some code
client = new ApacheAtlasUtils().createClient();
//some code
}
I am writing unit test for service method and I am getting exception for createClient method asking for values for url, username and password which should not happen as this should be mocked but the mocking is giving me below error
java.lang.IllegalArgumentException: Base URL cannot be null or empty.
at com.google.common.base.Preconditions.checkArgument(Preconditions.java:141)
at org.apache.atlas.AtlasServerEnsemble.<init>(AtlasServerEnsemble.java:35)
at org.apache.atlas.AtlasBaseClient.determineActiveServiceURL(AtlasBaseClient.java:318)
at org.apache.atlas.AtlasBaseClient.initializeState(AtlasBaseClient.java:460)
at org.apache.atlas.AtlasBaseClient.initializeState(AtlasBaseClient.java:448)
at org.apache.atlas.AtlasBaseClient.<init>(AtlasBaseClient.java:132)
at org.apache.atlas.AtlasClientV2.<init>(AtlasClientV2.java:82)
at com.jlr.stratus.commons.utils.ApacheAtlasUtils.createClient(ApacheAtlasUtils.java:40)
at com.jlr.stratus.rest.service.impl.FileSearchService.findFilesWithPages(FileSearchService.java:49)
The Test code is as follows:-
private FileSearchService fileSearchService;
#Spy
private ApacheAtlasUtils apacheAtlasUtils;
#Mock
private AtlasClientV2 client;
#Before
public void setup() {
MockitoAnnotations.initMocks(this);
fileSearchService = new FileSearchService();
}
#Test
public void findFilesWithPages_searchAll() throws AtlasServiceException {
Mockito.doReturn(client).when(apacheAtlasUtils).createClient();
service.search(queryParent,pageable);
}
Your idea with spying is adequate (you can even go for mocking if you do not actually need any true implementation of that class).
The problem lies in the implementation:
// Some code
client = new ApacheAtlasUtils().createClient();
//some code
}
Instead of having the ApacheAtlasUtils as an instance variable (or a supplier method) you create the instance on the fly.
Mockito is not smart enough to catch that operation and replace the real object with you spy.
With the supplier method you can set up your test as follows:
#Spy
private FileSearchService fileSearchService = new FileSearchService();
#Spy
private ApacheAtlasUtils apacheAtlasUtils = new ApacheAtlasUtils();
#Mock
private AtlasClientV2 client;
#Before
public void setup() {
MockitoAnnotations.initMocks(this);
doReturn(apacheAtlasUtils).when(fileSearchService).getApacheUtils();
}
in your SUT:
#Override
public Page<SearchResultDto> findFilesWithPages(QueryParent queryParent, Pageable pageable)
throws AtlasServiceException {
// Some code
client = getApacheUtils().createClient();
//some code
}
ApacheAtlasUtils getApacheUtils(){
return new ApacheAtlasUtils();
}
I had some trouble setting up unit test with my spring boot application. My main issue is with the "model" object that's needed in my controller, but I can't find a way to recreate it in my test, which is required to use my function.
here are the function I want to test
#Controller
public class AjoutAbscenceControler {
#Autowired
private AbsenceRepository absenceRepository;
#RequestMapping(value = { "/addAbsence" }, method = RequestMethod.GET)
public String showAddAbsencePage(Model model) {
Absence absence = new Absence();
model.addAttribute("Absence", absence);
return "addAbsence";
}
#RequestMapping(value = { "/addingAbsence" }, method = RequestMethod.POST)
public String saveAbsence(Model model, #ModelAttribute("absence") Absence absence) {
if (absence.getName() != null && absence.getName().length() > 0) {
absenceRepository.save(absence);
}
return "redirect:/userList";
}
}
I did try something like that
#RunWith(MockitoJUnitRunner.class)
public class AjoutAbscenceControlerTest {
#Mock
VacationRepository vacationRepository;
#Mock
CategoryRepository categoryRepository;
#InjectMocks
AjoutAbscenceControler controler;
public MockMvc mockMvc;
#Before
public void setUp() throws Exception{
mockMvc = MockMvcBuilders.standaloneSetup(controler).build();
}
#Test
public void showAddAbsencePagetest() {
AjoutAbscenceControler ajoutAbscenceControler =new AjoutAbscenceControler();
assertEquals("addAbsence",ajoutAbscenceControler.showAddAbsencePage(controler));
}
}
but I don't find any way to create a springfarmwork.ui.Model
If you're testing the logic of your controller you probably shouldn't create a Model object, but mock it, and verify the interactions against it:
#Mock
private Model model;
#Test
public void showAddAbsencePagetest() {
// Should probably be initialized in a #Before method,
// Initialized here for clarity only
AjoutAbscenceControler ajoutAbscenceControler = new AjoutAbscenceControler();
assertEquals("addAbsence", ajoutAbscenceControler.showAddAbsencePage(model));
Mockito.verify(model).addAttribute(eq("Absence"), any(Absence.class));
}
Currently using Mockito to Test a method from one of my classes. My class contains a List, and the method takes in an object of the same class. The issue is when I attempt to iterate over the List from the object. I'm getting a null pointer to the list. Below you will see the code snippets.
private Shipment shipment;
private Shipment shipment2;
#Mock
private Order mockOrder1;
#Mock
private Order mockOrder2;
#Mock
private Order mockOrder3;
#Mock
private ArrayList<Order> mockShipmentOrders;
#Mock
private ArrayList<Order> mockShipmentOrders2;
#Before
public void setUp(){
MockitoAnnotations.initMocks(this);
mockShipmentOrders.add(mockOrder1);
mockShipmentOrders.add(mockOrder2);
mockShipmentOrders2.add(mockOrder3);
shipment = new Shipment(1, mockShipmentOrders);
shipment2 = new Shipment(2, mockShipmentOrders2);
}
#Test
public void test_mergeShipments_increasesByOneWhenAShipmentOfOneAddedToAShipmentORderSizeOfTwo(){
shipment.mergeShipments(shipment2);
assertEquals(3, shipment.getShipmentOrders().size());
}
above you can see my mockito test and below is my Class with the method:
public class Shipment {
private long shipmentID;
private List<Order> shipmentOrders;
public Shipment(long shipmentID, List<Order> shipmentOrders){
this.shipmentID = shipmentID;
this.shipmentOrders = shipmentOrders;
}
public List<Order> getShipmentOrders(){
return shipmentOrders;
}
public void mergeShipments(Shipment shipment2){
List<Order> existingShipment = shipment2.getShipmentOrders();
for (Order order : existingShipment){
shipmentOrders.add(order);
}
}
When I run the test I am getting a java.lang.NullPointerException for the line: for (Order order : existingShipment){
in mergeShipemts();
The question is; Is it possible to mock a list, call that list and then run a foreach over that mocked list?
There are some fundamental issues why your example not does work and throws a NullPointerException.
The call to add() on the mocked list effectively doesn't do anything. All void methods on mocks are "no-ops" by default
Iterating over a list using for-each syntax calls Collection.iterator() under the hood. This returns null, because you've not setup mockito to return anything else.
Instead, I would not mock the list and instead pass an actual list. Arrays.asList() is convenient for testing.
#Before
public void setUp(){
MockitoAnnotations.initMocks(this);
shipment = new Shipment(1, Arrays.asList(mockOrder1, mockOrder2));
shipment2 = new Shipment(2, Arrays.asList(mockOrder3));
}
If you're determined to mock a list then you'll have to mock its behaviour, i.e. making the add() actually store something and .iterator() return an iterator. This can be done rather painfully as follows. I've only included this to demonstrate the principle.
#Mock
private List<String> mockedList;
#Before
public void init() {
MockitoAnnotations.initMocks(this);
List<String> realList = new ArrayList<>();
doAnswer(new Answer<String>() {
#Override
public String answer(InvocationOnMock invocation) throws Throwable {
realList.add(invocation.getArgumentAt(0, String.class));
return null;
}
}).when(mockedList).add(any());
when(mockedList.iterator()).thenAnswer(new Answer<Iterator<String>>() {
#Override
public Iterator<String> answer(InvocationOnMock invocation) throws Throwable {
return realList.iterator();
}
});
mockedList.add("bar");
mockedList.add("baz");
}
#Test
public void iterateOverMockedList() {
for (String each : mockedList) {
System.out.println(each);
}
}
As #Adam says: "Iterating over a list using for-each syntax calls Collection.iterator() under the hood. This returns null because you've not setup mockito to return anything else."
So you have to setup mockito in this way;
#Test
public void test_mergeShipments_increasesByOneWhenAShipmentOfOneAddedToAShipmentORderSizeOfTwo(){
//GIVEN
//Mock the iterator
Iterator<Order> stockIteratorMock = mock(Iterator.class);
//WHEN
//In setUp method you put two objs
when(mockShipmentOrder.size()).thenReturn(2);
//Set a mock for iterator
when(mockShipmentOrder.iterator()).thenReturn(iteratorMock);
// Instruct the iteratorMock when stop to return item
when(iteratorMock.hasNext())
.thenReturn(true)
.thenReturn(true)
.thenReturn(false);
// Instruct the iteratorMock what obj return on each call
// You can skip this: mockShipmentOrders.add(mockOrder1);
when(stockIteratorMock.next())
.thenReturn(mockOrder1)
.thenReturn(mockOrder2);
shipment.mergeShipments(shipment);
//THEN
assertEquals(2, shipment.getShipmentOrders().size());
}
This way is verbose, but you are free to modify the behaviour of the array list and also understand how it works under the wood.
You can't add values to the Mocked element. you can remove #Mock from the list of data and use new keyword to initilize it.
private Shipment shipment;
private Shipment shipment2;
#Mock
private Order mockOrder1;
#Mock
private Order mockOrder2;
#Mock
private Order mockOrder3;
private ArrayList<Order> mockShipmentOrders;
private ArrayList<Order> mockShipmentOrders2;
#Before
public void setUp(){
MockitoAnnotations.initMocks(this);
mockShipmentOrders = new ArrayList<>();
mockShipmentOrders2 = new ArrayList<>();
mockShipmentOrders.add(mockOrder1);
mockShipmentOrders.add(mockOrder2);
mockShipmentOrders2.add(mockOrder3);
shipment = new Shipment(1, mockShipmentOrders);
shipment2 = new Shipment(2, mockShipmentOrders2);
}
#Test
public void test_mergeShipments_increasesByOneWhenAShipmentOfOneAddedToAShipmentORderSizeOfTwo(){
System.out.println(shipment);
System.out.println(shipment2);
shipment.mergeShipments(shipment2);
assertEquals(3, shipment.getShipmentOrders().size());
}
The following code returns Expectation failure of verification:
What's up with the code?
can someone help me what am I missing there?
public class DAOImplTest {
private DAOImpl dao;
private JdbcTemplate mockJdbcTemplate;
#Before
public void before() {
dao = new DAOImpl();
mockJdbcTemplate = createMock(JdbcTemplate.class);
dao.setJdbcTempate(mockJdbcTemplate);
}
#After
public void after() {
dao = null;
}
#SuppressWarnings("unchecked")
#Test
public void methReturnsWhenOrgIdsAndGuidFound(){
final String expectedOrgIds = "d514d112566e";
final String expectedGUID = "one";
expect(mockJdbcTemplate.queryForObject(eq(SSOSASguidDAOImpl.GET_GUID_FOR_ORG_IDS),
(RowMapper<String>) anyObject(), eq(expectedGUID), eq(expectedOrgIds))).andReturn(expectedOrgIds);
replay(mockJdbcTemplate);
// verify(mockJdbcTemplate, expectedOrgIds);
verify(mockJdbcTemplate);
assertNotNull(expectedOrgIds);
assertEquals("d514d112566e", expectedOrgIds);
}
}
Wondering why it is throwing an error on verify?
The call to replay should be followed by a call the the expected methods, in your case, you should call the mockJdbcTemplate.queryForObject(); method with appropriate parameters; before calling the verfiy method.