How to cover a method calling a static method using JUnit mocking? - java

Consider two classes A and B.
class A { static int a(){} }
class B { void something(){ int value=A.a(); .......}}
Now I have to cover class B using Junit Test case and hence I create a new class (class TestB) to cover the class B.
class TestB { #Test public void testsomething(){...} }
Here my question is if there is any way I can cover the line A.a() as this is the static method. I know that I can't easy mock it because there is no object involved. So how would I proceed?
I am using JUnit and EasyMock.

As you pointed out there is no way to mock a static method with easymock.
Approach 1: Don't use static methods wherever possible.
Approach 2: Use PowerMock on top of easymock.
Approach 3: Delegate the body of A.a() by using a supplier inside a(). You can than use a "simple" supplier for testcases and the real world supplier for productive use.

You will have to use PowerMock along with easymock to mock the static methods.
https://github.com/jayway/powermock/wiki/MockStatic
For your test case mock code will look like this
KeyStore aMock = PowerMockito.mock(A.class);
PowerMockito.when(A.a()).thenReturn(0);
Here is a working example to mock static method for KeyStore.getInstance method
KeyStoreService:
package com.foo;
import java.io.IOException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
public class KeyStoreService {
public KeyStoreService(){
}
public void load() throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException{
System.out.println("start");
KeyStore ks = KeyStore.getInstance("");
ks.load(null, null);
System.out.println("end");
}
}
Test class:
package com.foo.test;
import java.io.IOException;
import java.io.InputStream;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.cert.CertificateException;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Matchers;
import org.mockito.Mockito;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import com.foo.KeyStoreService;
#PrepareForTest(KeyStoreService.class)
#RunWith(PowerMockRunner.class)
public class TestKeyStore {
#Test
public void test1() throws KeyStoreException, NoSuchProviderException, NoSuchAlgorithmException, CertificateException, IOException{
PowerMockito.mockStatic(KeyStore.class);
KeyStore keyStoreMock = PowerMockito.mock(KeyStore.class);
KeyStoreService kss = new KeyStoreService();
PowerMockito.when(KeyStore.getInstance(Matchers.anyString(), Matchers.anyString())).thenReturn(keyStoreMock);
Mockito.doNothing().when(keyStoreMock).load(Mockito.any(InputStream.class), Mockito.any(char[].class));
kss.load();
}
}

Related

Mock unit test a Service implementation that calls a Stored Procedure in Java

I’m trying to unit test a Service implementation that calls a Stored Procedure in Java.
My idea is to Mock or Stub the service just to see if all the calls are made correctly.
Not quite sure how to do this.
I’m using Springframework for the Service.
Any ideas on how to easily do this ? I'm getting null of course for the
#Autowired
private PerformanceService performanceService;
which doesn't initially happen, anyway I just want to Mock that and just make sure the calls are happening, thanks.
import com.integration.as400.entity.Performance;
import com.integration.as400.service.PerformanceService;
import org.junit.Before;
import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.mockito.MockitoAnnotations;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.Configuration;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.mockito.BDDMockito.mock;
import static org.mockito.Mockito.when;
#Configuration
#RunWith(SpringRunner.class)
#SpringBootTest
#ContextConfiguration(classes={PerformanceService.class, TestConfiguration.class})
#ActiveProfiles("test")
public class PerformanceServiceImplMockTest {
private static final Logger logger = LoggerFactory.getLogger(PerformanceServiceImplMockTest.class);
#Autowired
private PerformanceService performanceService;
#Before
public void setupMock(){
MockitoAnnotations.initMocks(this);
performanceService = mock(PerformanceService.class);
}
#Test
public void shouldReturnListPerformance_whenGetListPerformanceIsCalled() throws Exception{
List<Performance> performances = new ArrayList<>();
performances.add(new Performance("0000184","00001","MWR","SI",LocalDate.parse("2016-01-01"),LocalDate.parse("2016-01-31"),"CAD",48585.63,34821.01,47501.47,-94372.00,11184.70,10.000322,"",33105.91));
performances.add(new Performance("0000184","00001","MWR","SI",LocalDate.parse("2016-01-01"),LocalDate.parse("2016-01-31"),"CAD",142743.11,260376.38,41688.49,-4886.00,11184.70,35937.14,"",7.475078));
logger.info("Stubbing getListPerformance(int pageNumber, String loadStartDate, String loadEndDate) to return " + performances);
// Arrange
when(performanceService.getListPerformance(2, "2021-08-01", "2021-08-31")).thenReturn(performances);
// Act
List<Performance> retrievedPerformances = performanceService.getListPerformance(2, "2021-08-01", "2021-08-31");
// Assert
assertThat(retrievedPerformances, is(equalTo(performances)));
}
}

Powermock's Mock Static is not working as expected

For my project, I am working on power mock framework for unit testing.
I am facing an issue, I have mocked a static method, but still, it is calling the real method. I have set up the problem with simple classes. Please help to resolve the issue.
This is the Test that is being tested and it has a static method.
package in.service;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class ConnectionClass {
public static boolean getValue() throws SQLException {
Connection connection = DriverManager.getConnection("", "", "");
return connection == null;
}
}
This is the test class.
package in.service;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.when;
#RunWith(PowerMockRunner.class)
#PrepareForTest({DriverManager.class})
public class ConnectionClassTest {
#Mock
private Connection connection;
#Before
public void setUp() {
PowerMockito.mockStatic(DriverManager.class);
}
#Test
public void check_Value_WhenConnectionIsNotPresent() throws SQLException {
when(DriverManager.getConnection(anyString(), anyString(), anyString())).thenReturn(connection);
ConnectionClass.getValue();
}
#Test
public void check_Value_WhenConnectionIsPresent() throws SQLException {
when(DriverManager.getConnection(anyString(), anyString(), anyString())).thenReturn(null);
ConnectionClass.getValue();
}
}
When I try to run these tests, DriverManager's actual connection method is called. Ideally, this method shouldn't be called.
Please help here if I am doing anything wrong here.

Stubbing static methods in Mockito 2 throws InvalidUseOfMatchersException

I have a class where I'm using Powermock + Mockito to suppress a static method in a utility class. It works fine with Powermock 1.6.2 and Mockito 1.10.19, but I've been tasked with moving to Java 10 (JRE: we're still compiling with Java 8) and so I've moved to Powermock 2 (currently in beta) and Mockito 2.16.1. Now, I consistently get org.mockito.exceptions.misusing.InvalidUseOfMatchersException:
Misplaced or misused argument matcher detected here.
A simple example, MyMockito.java:
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import java.lang.reflect.Method;
import static org.mockito.Mockito.any;
import static org.powermock.api.mockito.PowerMockito.spy;
import static org.powermock.api.mockito.PowerMockito.when;
import static org.powermock.api.support.membermodification.MemberMatcher.method;
import static org.powermock.api.support.membermodification.MemberModifier.suppress;
#RunWith(PowerMockRunner.class)
#PrepareForTest(StringMeasurer.class)
public class MyMockito {
#Test
public void testSuppressMethod() throws Exception {
spy(StringMeasurer.class);
Method measure = method(StringMeasurer.class, "measure", String.class);
suppress(measure);
when(StringMeasurer.class, measure)
.withArguments(any(String.class))
.thenReturn(10);
System.out.println(StringMeasurer.measure("Hello"));
}
And StringMeasurer.java:
public class StringMeasurer {
private StringMeasurer() {}
public static int measure(String s) {
return s.length();
}
}
}
I'm assuming that either there have been some changes to how matchers can be used to match arguments in stubbed static methods, or else this should never have worked and somehow got through in Mockito 2 (or possibly this is a bug in the Powermock beta). Can anyone provide me some insight into what I'm doing wrong?
Working solution for PowerMock 2.0.0-beta.5:
import static org.mockito.ArgumentMatchers.any;
import static org.powermock.api.mockito.PowerMockito.when;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
#RunWith(PowerMockRunner.class)
#PrepareForTest(StringMeasurer.class)
public class MyMockito {
#Test
public void testSuppressMethod() throws Exception {
PowerMockito.mockStatic(StringMeasurer.class);
when(StringMeasurer.measure(any(String.class))).thenReturn(10);
System.out.println(StringMeasurer.measure("Hello"));
}
}
More details can be found in the official PowerMock documentation: Mocking Static Method
The question uses the PowerMockito.spy() method, which is required for partial mocking, although the example given only has one static method, so that's not necessary here. Here's a working solution that uses partial mocking for an extended example:
MyMockito.java:
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import java.lang.reflect.Method;
import java.util.List;
import static junit.framework.Assert.assertEquals;
import static org.mockito.Mockito.*;
import static org.powermock.api.support.membermodification.MemberMatcher.method;
import static org.powermock.api.mockito.PowerMockito.doReturn;
import static org.powermock.api.mockito.PowerMockito.spy;
#RunWith(PowerMockRunner.class)
#PrepareForTest(StringMeasurer.class)
public class MyMockito {
#Test
public void testSuppressMethod() throws Exception {
spy(StringMeasurer.class);
Method measure = method(StringMeasurer.class, "measure", String.class);
doReturn(10).when(StringMeasurer.class, measure)
.withArguments(any(String.class));
System.out.println(StringMeasurer.measure("Hello"));
List<String> dummy = StringMeasurer.dummy(5);
assertEquals(5, dummy.size());
dummy.forEach(System.out::println);
}
}
And StringMeasurer.java:
import java.util.ArrayList;
import java.util.List;
public class StringMeasurer {
private StringMeasurer() {}
public static int measure(String s) {
return s.length();
}
public static List<String> dummy(int size) {
List<String> list = new ArrayList<>();
for (int i = 0; i < size; i++) {
list.add("" + i);
}
return list;
}
}
Note that, in this case, the accepted solution would mock the StringMeasurer.dummy() method as well, returning an empty list, and the test would fail on the assertEquals().

JUnit Mock test returns null on using InjectMocks

I am trying to unit test my service class but the mock returns null
package com.tgt.store.pricetask.pricetask_service;
import com.tgt.store.pricetask.model.PriceTaskMaster;
import com.tgt.store.pricetask.model.TaskModel;
import com.tgt.store.pricetask.repository.PriceTaskMasterRepository;
import com.tgt.store.pricetask.service.DataMigrationService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import java.time.LocalDateTime;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.*;
#RunWith(SpringJUnit4ClassRunner.class)
public class DataMigrationServiceTest {
#Mock
PriceTaskMasterRepository priceTaskMasterRepository;
#InjectMocks
DataMigrationService dataMigrationService;
#Test
public void
testPriceTaskMasterService_whenTaskModelPassed_thenSavePriceTaskMaster() {
TaskModel taskModel = new TaskModel.TaskModelBuilder().setTaskID(1)
.setDueDate("2017-11-01T11:41:00+0000").setIsAlertable("A").setIsPriority("P").setLocationid("1234")
.createTaskModel();
PriceTaskMaster priceTaskMaster = new PriceTaskMaster.PriceTaskMasterBuilder().setId(1L).setTaskStatus("A")
.setAlertable("A").setPriority("P").setLocationId(1234)
.setDueDate(LocalDateTime.now()).createPriceTaskMaster();
when(priceTaskMasterRepository.insertPriceTaskMaster(any(PriceTaskMaster.class))).thenReturn(priceTaskMaster);
PriceTaskMaster savedPriceTaskMaster = dataMigrationService.savePriceTaskMaster(taskModel);
assertNotNull(savedPriceTaskMaster);
assertEquals("A", savedPriceTaskMaster.getTaskStatus());
assertEquals("P", savedPriceTaskMaster.getPriority());
assertEquals(1234, savedPriceTaskMaster.getLocationId().intValue());
assertEquals(123456789, savedPriceTaskMaster.getTcin().longValue());
verify((priceTaskMasterRepository), times(1)).insertPriceTaskMaster(priceTaskMaster);
}
}
In the above code, when call reaches the service class priceTaskMasterRepository is null. I am unable to figure out if I am missing something. I have tried RunWith SpringRunner and MockitoJUnitRunner but same result. Any help is appreciated.
Thank you in advance.
You will need to initialize the DataMigrationService field when using the #InjectMocks annotation. That will create an instance of the class under test as well as inject the mock objects into it.
#InjectMocks
DataMigrationService dataMigrationService = new DataMigrationService();
http://www.baeldung.com/mockito-annotations
If you're using JUnit to run your tests, then you should have something like this:
#Before
public void setup()
{
MockitoAnnotations.initMocks(this);
}
This ensures all your mocks are initialised. This is supposed to be unnecessary when using MockitoJUnitRunner.

powermock mocking constructor via whennew() does not work with anonymous class

I have a DummyResource class and a DummyTarget file, and a test class TestDummyResource as below, but the mocked object DummyResource dr = mock(DummyResource.class) only works when I call the constructor inside a normal class, when it's called in an anonymous class, it's calling the actual constructor instead of using the mocked object.
Versions:
powermock 1.4.12 mockito 1.9.0 junit 4.8.2
DummyTarget.java:
import java.io.IOException;
import java.io.OutputStream;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.StreamingOutput;
public class DummyTarget {
public StreamingOutput testMocking() {
return new StreamingOutput() {
#Override
public void write(OutputStream arg0) throws IOException, WebApplicationException {
new DummyResource();
}
};
}
}
DummyResource.java:
package com.smin.dummy;
public class DummyResource {
public DummyResource() {
System.out.println("mock failure");
}
}
TestDummyResource.java:
package com.smin.dummy;
import static org.mockito.Mockito.mock;
import java.io.IOException;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.StreamingOutput;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
#RunWith(PowerMockRunner.class)
#PrepareForTest({DummyResource.class,DummyTarget.class})
public class TestDummyResource {
#Before
public void setUp() throws Exception {
DummyResource dr = mock(DummyResource.class);
PowerMockito.whenNew(DummyResource.class).withNoArguments().thenReturn(dr);
}
#Test
public void testMocked() throws WebApplicationException, IOException {
new DummyResource(); // it uses the mocked object dr here,
//doesn't print "mock failure"
StreamingOutput sop = new DummyTarget().testMocking();
sop.write(null); // it calls DummyResource's constructor,
// prints ""mock failure"" here
}
}
You need to have prepared the class calling the constructor, not the class on which the constructor is called, the following should fix you up:
#PrepareForTest(DummyTarget.class)
For more information check this page.
It looks like an anonymous class may inherit the package of the class that defines it. Can you try the wildcard form of PrepareForTest?:
#PrepareForTest("com.smin.dummy.*")
If that doesn't work, you could try the shotgun PrepareEverythingForTest Annotation.
Actually, you have to prepare for test the class that makes the constructor call, not the class on which the constructor was called. See https://github.com/jayway/powermock/wiki/MockConstructor.
In your case, you should use #PrepareForTest(DummyTarget.class)
I had the same problem, and resolved it with using whenNew with fully qualified name. The fully qualified name of an inner anonymous class in your case is:
DummyTarget.class + "$1"
so you should create a mock of that class:
DummyResource dr = mock(Class.forName(DummyTarget.class + "$1"));
and it will work for you.
Also, don't forget to prepare the DummyTarget class:
#PrepareForTest(DummyTarget.class)
Hope it helped =]

Categories

Resources