powermockito spy private void method invocation - unit-testing

For a test class with a private void method, what is the right way to mock the behaviour of the method. The solution below invokes the method instead.
public class TestWizard {
private void testOne(){
throw new NullPointerException();
}
private void testTwo(){
testOne();
}
}
#RunWith(PowerMockRunner.class)
#PrepareForTest({TestWizard.class})
public class WTest {
#Test
public void testWizard() throws Exception {
TestWizard wizard2 = Whitebox.newInstance(TestWizard.class);
TestWizard wizard = Mockito.spy(wizard2);
PowerMockito.doNothing().when(wizard, "testTwo");
}
}
The error is:
java.lang.NullPointerException
at tuk.pos.wizard.model.TestWizard.testOne(TestWizard.java:6)
at tuk.pos.wizard.model.TestWizard.testTwo(TestWizard.java:10)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.powermock.reflect.internal.WhiteboxImpl.performMethodInvocation(WhiteboxImpl.java:1862)
at org.powermock.reflect.internal.WhiteboxImpl.doInvokeMethod(WhiteboxImpl.java:824)
at org.powermock.reflect.internal.WhiteboxImpl.invokeMethod(WhiteboxImpl.java:689)
at org.powermock.reflect.Whitebox.invokeMethod(Whitebox.java:401)
at org.powermock.api.mockito.internal.expectation.PowerMockitoStubberImpl.when(PowerMockitoStubberImpl.java:105)

Use PowerMockito.spy(...) instead of Mockito.spy(...).
Tested with PowerMockito 2.0.5
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;
import org.powermock.reflect.Whitebox;
#RunWith(PowerMockRunner.class)
#PrepareForTest(WTest.TestWizard.class)
public class WTest {
public class TestWizard {
private void testOne(){
throw new NullPointerException();
}
private void testTwo(){
testOne();
}
}
#Test
public void testWizard() throws Exception {
TestWizard spy = PowerMockito.spy(Whitebox.newInstance(TestWizard.class));
PowerMockito.doNothing().when(spy, "testTwo");
spy.testTwo();
}
}
Try to restrict the usage of spies to legacy code. In most other cases a refactoring should be the preferred solution.

Related

Unit testing Placeholder defaultValue in #RequestParam

I'm trying to test my controller that has a handler with a RequestParam configured with a default value pointed to a placeholder:
#Controller
public class AgeController {
#GetMapping("/age")
public String home(#RequestParam(name="current", defaultValue="${default.age}") Integer age) {
return "age"+age;
}
}
This works fine when I'm testing through my browser but when I use the following test case, it throws an exception:
Test Case:
public class AgeControllerTest {
AgeController controller
MockMvc mockMvc;
#Before
public void setUp() {
ageController = new AgeController();
mockMvc = MockMvcBuilders.standaloneSetup(controller).addPlaceholderValue("default.age", "10").build();
}
#Test
public void test() {
mockMvc.perform(get("/age")).andExpect(status().isOk());
}
}
Exception:
Caused by: java.lang.NumberFormatException: For input string: "${default.age}"
at java.lang.NumberFormatException.forInputString(Unknown Source)
at java.lang.Integer.parseInt(Unknown Source)
at java.lang.Integer.valueOf(Unknown Source)
at org.springframework.util.NumberUtils.parseNumber(NumberUtils.java:208)
at org.springframework.beans.propertyeditors.CustomNumberEditor.setAsText(CustomNumberEditor.java:113)
at org.springframework.beans.TypeConverterDelegate.doConvertTextValue(TypeConverterDelegate.java:468)
at org.springframework.beans.TypeConverterDelegate.doConvertValue(TypeConverterDelegate.java:441)
at org.springframework.beans.TypeConverterDelegate.convertIfNecessary(TypeConverterDelegate.java:199)
at org.springframework.beans.TypeConverterDelegate.convertIfNecessary(TypeConverterDelegate.java:108)
at org.springframework.beans.TypeConverterSupport.doConvert(TypeConverterSupport.java:64)
at org.springframework.beans.TypeConverterSupport.convertIfNecessary(TypeConverterSupport.java:47)
at org.springframework.validation.DataBinder.convertIfNecessary(DataBinder.java:713)
at org.springframework.web.method.annotation.AbstractNamedValueMethodArgumentResolver.resolveArgument(AbstractNamedValueMethodArgumentResolver.java:120)
Consider using #TestPropertySource.
#TestPropertySource(properties = {"default.age = 10"})
public class AgeControllerTest {
...
}

How to mock another static method in the same class which is being tested?

I am writing JUnit Test case with Mockito for a class which has two methods methodA,methodB. I would like to mock the call to the methodA from methodB in my test case.Some one help me.pls
Here is the class:
public Class Test{
public static List<Object> methodA() {
...
return list;
}
public static List<Object> methodB() {
...
list = methodA();
return list;
}
}
You will need to use PowerMockito to mock the static method.
Example:
package unitest;
import java.util.ArrayList;
import java.util.List;
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(unitest.Test.class)
public class TestTest {
#Test
public void testMethodB() {
PowerMockito.mockStatic(unitest.Test.class);
PowerMockito.when(unitest.Test.methodA()).thenReturn(new ArrayList());
List b = unitest.Test.methodB();
org.junit.Assert.assertNotNull(b);
}
}

Mocking static methods with Powermockito

I am trying to mock static method with PowerMockito. I have referred to various stackoverflow answers such as this:Mocking static methods with PowerMock and Mockito
But I am getting : org.mockito.exceptions.misusing.InvalidUseOfMatchersException:
Misplaced argument matcher detected here exception.
I have spent hours debugging my code and google searching but to no avail. What am I missing here?
* Note: I am running it as a testng test. *
I have added comments in my code that may help you understand what I am trying to do.
The full stack trace is:
org.mockito.exceptions.misusing.InvalidUseOfMatchersException:
Misplaced argument matcher detected here:
at MyClassTest.testMethod1(MyClassTest.java:24)`
You cannot use argument matchers outside of verification or stubbing.
Examples of correct usage of argument matchers:
when(mock.get(anyInt())).thenReturn(null);
doThrow(new RuntimeException()).when(mock).someVoidMethod(anyObject());
verify(mock).someMethod(contains("foo")) `
Also, this error might show up because you use argument matchers with methods that cannot be mocked.
Following methods *cannot* be stubbed/verified: final/private/equals()/hashCode().
Mocking methods declared on non-public parent classes is not supported.`
at MyClassTest.testMethod1(MyClassTest.java:24)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:84)
at org.testng.internal.Invoker.invokeMethod(Invoker.java:714)
at org.testng.internal.Invoker.invokeTestMethod(Invoker.java:901)
at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:1231)
at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:127)
at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:111)
at org.testng.TestRunner.privateRun(TestRunner.java:767)
at org.testng.TestRunner.run(TestRunner.java:617)
at org.testng.SuiteRunner.runTest(SuiteRunner.java:348)
at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:343)
at org.testng.SuiteRunner.privateRun(SuiteRunner.java:305)
at org.testng.SuiteRunner.run(SuiteRunner.java:254)
at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:52)
at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:86)
at org.testng.TestNG.runSuitesSequentially(TestNG.java:1224)
at org.testng.TestNG.runSuitesLocally(TestNG.java:1149)
at org.testng.TestNG.run(TestNG.java:1057)
at org.testng.remote.AbstractRemoteTestNG.run(AbstractRemoteTestNG.java:132)
at org.testng.remote.RemoteTestNG.initAndRun(RemoteTestNG.java:230)
at org.testng.remote.RemoteTestNG.main(RemoteTestNG.java:76)
`
Below is my code:
Test Class
import static org.mockito.Matchers.anyString;
import org.junit.runner.RunWith;
import org.mockito.BDDMockito;
import org.mockito.Mockito;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import org.testng.annotations.Test;
#Test
#RunWith(PowerMockRunner.class)
#PrepareForTest(AnotherClass.class)
public class MyClassTest {
MyClass myClass;
#Test
public void testMethod1() {
/*
* Mock static methods
*/
PowerMockito.mockStatic(AnotherClass.class);
BDDMockito.given(AnotherClass.yetAnotherMethod(anyString())).willReturn(Mockito.mock(String.class));
// call the method of system under test
myClass.method1();
// verify
PowerMockito.verifyStatic();
}
}
System Under Test:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
public class MyClass {
public String method1() {
String result = AnotherClass.yetAnotherMethod("Pramithas");
return result;
}
}
AnotherClass.java:
import org.springframework.stereotype.Service;
public class AnotherClass {
public static String yetAnotherMethod(String s) {
return s;
}
}
You haven't created new object for MyClass
Do not try to mock primitive types or final classes
Removed #Test annotation
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.mockito.Matchers.anyString;
import org.mockito.BDDMockito;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
#RunWith(PowerMockRunner.class)
#PrepareForTest(AnotherClass.class)
public class MyClassTest {`
MyClass myClass = new MyClass();
#Test
public void testMethod1() {
/*
* Mock static methods
*/
PowerMockito.mockStatic(AnotherClass.class);
BDDMockito.given(AnotherClass.yetAnotherMethod(anyString())).willReturn("any String");
// call the method of system under test
myClass.method1();
// verify
PowerMockito.verifyStatic();
}
}
This is verified. It should work.
I got your example working with some changes:
#RunWith(PowerMockRunner.class)
#PrepareForTest({ AnotherClass.class })
public class MyClassTest {
#Before
public void setUp() {
myClass = new MyClass();
}
#Test
public void testMethod1() {
/*
* Mock static methods
*/
PowerMockito.mockStatic(AnotherClass.class);
BDDMockito.given(AnotherClass.yetAnotherMethod(Mockito.anyString())).willReturn("Hello");
// call the method of system under test
String a = myClass.method1();
// verify
PowerMockito.verifyStatic();
}
I added AnotherClass to PrepareForTest too and I force AnotherClass mock to return a String value because Mockito can't mock final classes and I can check that myClass behave as expected. Here is my Mockito and Powermock dependencies:
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>2.7.5</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-module-junit4</artifactId>
<version>1.7.0RC2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-api-mockito2</artifactId>
<version>1.7.0RC2</version>
<scope>test</scope>
</dependency>

Getting null response while creating Mock Dao using Mockito

I am trying to create a mock data for Dao class. Test case is running successfully but it is returning null data. I searched and implemented #Mock, #InjectMocks, Inititated MockitoAnnotation but still it is not working. The project is in spring. Context path is also correct. I have not used any other methods. First for running I am trying to just call a method and print. Please help me to solve this error.
RegionManager Class:
#Service("regionManager")
public class RegionManager implements RegionManagerIntf {
#Autowired
RegionDaoIntf regionInquiry;
private RegionDao regionDao;
#Override
public ListPojo retrieveData(String Id, String details, String code) {
return regionInquiry.retrievePData(Id, details, code);
}
public RegionDao getRegionDao() {
return regionDao;
}
public void setRegionDao(RegionDao regionDao) {
this.regionDao = regionDao;
}
}
Dao Class:
#Component
public class RegionProcessorFactory implements RegionProcessorIntf {
private static final Logger logger = Logger
.getLogger(RegionProcessorFactory.class);
#Override
public ListPojo retrieveData(String Id,
String details, String code) {
ListPojo listPojo = new ListPojo();
//Do some action
return listPojo;
}
}
ListPojo:
It contains getter setters.
Test Class:
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.runners.MockitoJUnitRunner;
import org.springframework.test.context.ContextConfiguration;
import com.fasterxml.jackson.databind.ObjectMapper;
#RunWith(MockitoJUnitRunner.class)
#ContextConfiguration({"classpath*:spring/beanRefContext.xml"})
public class RegionManagerTest
{
private String Id = "12345";
private String Code = "123";
private String details = "12";
ObjectMapper mapper;
#Mock
private RegionProcessorFactory dao;
#Mock
private ListPojo listPojo;
#InjectMocks
private RegionManager service;
/**
* Before method will be called before executing every test case
*/
#Before
public void initialize() {
System.out.println("In initialize");
MockitoAnnotations.initMocks(this);
dao = mock(RegionProcessorFactory.class);
listPojo = mock(ListPojo.class);
service = new RegionManager();
service.setRegionDao(dao);
}
#Test
public void CreateDatabaseMock() throws Exception
{
System.out.println("dao result :: "+dao.retrieveData(Id, "", ""));
when(dao.retrieveData(Id, "", "")).thenReturn(listPojo);
verify(dao).retrieveData(Id, "", "");
}
/**
* After method will be called after executing every test case
*/
#After
public void TearDownClass() {
}
}
First: If you are using #RunWith(MockitoJUnitRunner.class) there is no need for MockitoAnnotations.initMocks(this); more on that here
Second: Everything with #Mock will be mocked and mockito will try to inject it into object annotated with #InjectMocks which mockito will instantiate(in old mockito versions you had to create the object yourself) so following lines are not needed:
dao = mock(RegionProcessorFactory.class);
listPojo = mock(ListPojo.class);
service = new RegionManager();
service.setRegionDao(dao);
Third: The actual execution should come after stubbing
#Test
public void CreateDatabaseMock() throws Exception{
when(dao.retrieveData(Id, "", "")).thenReturn(listPojo);
System.out.println("dao result :: "+dao.retrieveData(Id, "", ""));
verify(dao).retrieveData(Id, "", "");
}

Testing Katharsis JsonApi with MockMvc and Mockito

I would like to test the behaviour configured by my Katharsis ResourceRepository (katharsis-spring 2.1.7):
import io.katharsis.queryParams.QueryParams;
import io.katharsis.repository.ResourceRepository;
import org.springframework.stereotype.Component;
#Component
public class UserResourceRepository implements ResourceRepository<UserDTO, String> {
#Autowired
private UserRepository databaseRepository;
#Override
public UserDTO findOne(String email, QueryParams queryParams) {
return null;
}
#Override
public Iterable<UserDTO> findAll(QueryParams queryParams) {
return null;
}
#Override
public Iterable<UserDTO> findAll(Iterable<String> iterable, QueryParams queryParams) {
return null;
}
#Override
public void delete(String email) {
}
#Override
public UserDTO save(UserDTO s) {
return null;
}
}
I would like to test it in a similar way as I do it with normal, Spring Controllers, using Mockito to mock database repository and using MockMvc:
import org.junit.Before;
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.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import java.util.Optional;
import static org.mockito.Mockito.when;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
#RunWith(MockitoJUnitRunner.class)
public class UserJsonApiTest {
#InjectMocks
private UserResourceRepository resourceRepository;
#Mock
private UserRepository databaseRepository;
private MockMvc mockMvc;
#Before
public void setup() {
mockMvc = MockMvcBuilders.standaloneSetup(resourceRepository).build();
}
#Test
public void first() throws Exception {
Optional<UserEntity> user = Optional.of(new UserEntity().
id(1).
email("test#test").
firstName("test first name").
lastName("test last name").
pass("test pass"));
when(
databaseRepository.
findOneByEmail(user.get().getEmail())).
thenReturn(user);
mockMvc.perform(
get("/users/" + user.get().email())).
andExpect(status().isOk())
;
}
}
Obviously, this code doesn't work because my Katharsis UserResourceRepository is not really a Controller. So far I have learned (from logs) that it is actually using some filters mappings and class named io.katharsis.spring.KatharsisFilterV2.
Is there any way to use MockMvc for such test? If not - is there any other way I could test it without starting the whole server (with mocking)?
You could use an embedded Server - like UndertowJaxrsServer - and inject the KatharsisFeature:
Create a class (MyApp) which extends Application public static class MyApp extends Application { and deploy it to the embedded server server.deploy(MyApp.class);
in this Class, overwrite getClasses and add a second class (KatharsisFeatureTest) which implements Feature KatharsisFeatureTest implements Feature
in KatharsisFeatureTest you can then register a KatharsisFeature and there you can overwrite JsonServiceLocator and inject the mock.
Sound a little bit complicated, but works like charm :)
Have a look at my implementation.
.
#RunWith(MockitoJUnitRunner.class)
public class EndpointResourceTest {
#Mock
private EndpointService endpointService;
#InjectMocks
private final static EndpointResourceV1 endpointRessource = new EndpointResourceV1();
private static UndertowJaxrsServer server;
#BeforeClass
public static void beforeClass() throws Exception {
server = new UndertowJaxrsServer();
server.deploy(MyApp.class);
server.start();
}
#Test
public void testGetEndpoint() throws URISyntaxException {
Mockito.when(endpointService.getEndpoint("SUBMIT")).thenReturn(new EndpointDTO("SUBMIT", "a", "b"));
Client client = ClientBuilder.newClient();
Response response = client.target(TestPortProvider.generateURL("/api/endpoints/SUBMIT"))
.request(JsonApiMediaType.APPLICATION_JSON_API)
.get();
Assert.assertEquals(200, response.getStatus());
String json = response.readEntity(String.class);
Assert.assertTrue(json.contains("SUBMIT"));
Assert.assertTrue(json.contains("a"));
Assert.assertTrue(json.contains("b"));
Mockito.verify(endpointService, Mockito.times(1)).getEndpoint("SUBMIT");
}
#AfterClass
public static void afterClass() throws Exception {
server.stop();
}
#ApplicationPath("/api")
public static class MyApp extends Application {
#Override
public Set<Class<?>> getClasses() {
HashSet<Class<?>> classes = new HashSet<Class<?>>();
classes.add(KatharsisFeatureTest.class);
return classes;
}
}
public static class KatharsisFeatureTest implements Feature {
#Override
public boolean configure(FeatureContext featureContext) {
featureContext
.property(KatharsisProperties.RESOURCE_SEARCH_PACKAGE, "...")
.register(new io.katharsis.rs.KatharsisFeature(
new ObjectMapper(), new QueryParamsBuilder(new DefaultQueryParamsParser()), new SampleJsonServiceLocator() {
#Override
public <T> T getInstance(Class<T> clazz) {
try {
if (clazz.equals(EndpointResourceV1.class)) {
return (T) endpointRessource;
}
return clazz.newInstance();
}
catch (InstantiationException | IllegalAccessException e) {
throw new RuntimeException(e);
}
}
}));
return true;
}
}
}