org.mockito.MockingDetails.getMockHandler()Lorg/mockito/invocation/MockHandler - junit

I want to write the Unit test using PowerMockito/Mockito for my static method/void method.
But When I try to run , I got the following error:
/Users/<username>/Library/Java/JavaVirtualMachines/corretto-
---- IntelliJ IDEA coverage runner ----
sampling ...
include patterns:
exclude patterns:
ScriptEngineManager providers.next(): javax.script.ScriptEngineFactory: Provider jdk.nashorn.api.scripting.NashornScriptEngineFactory not a subtype
ScriptEngineManager providers.next(): javax.script.ScriptEngineFactory: Provider jdk.nashorn.api.scripting.NashornScriptEngineFactory not a subtype
java.lang.NoSuchMethodError: org.mockito.MockingDetails.getMockHandler()Lorg/mockito/invocation/MockHandler;
at org.powermock.api.mockito.invocation.MockHandlerAdaptor.getMockHandler(MockHandlerAdaptor.java:56)
at org.powermock.api.mockito.invocation.MockHandlerAdaptor.createInvocation(MockHandlerAdaptor.java:81)
at org.powermock.api.mockito.invocation.MockHandlerAdaptor.performIntercept(MockHandlerAdaptor.java:61)
at org.powermock.api.mockito.invocation.MockitoMethodInvocationControl.invoke(MockitoMethodInvocationControl.java:93)
at org.powermock.core.MockGateway.doMethodCall(MockGateway.java:186)
at org.powermock.core.MockGateway.doMethodCall(MockGateway.java:168)
at org.powermock.core.MockGateway.methodCall(MockGateway.java:138)
I am new to use powerMockito/Mockito, Can Anyone help to figure out the exact issue.
This is my CreateTaskBuilder Class method that I want to test:
Here JgitAccessor.clone() is a static void methid that I used donothing() for it.
public void Repository() throws DependencyFailureException, IOException, GitAPIException {
try {
ServiceAccessor.loadTmpSshTicket();
if (!Files.exists(Paths.get(LambdaEnv.GIT_SSH_SCRIPT.getValue()))) { // getValue will throw exception on null
throw new IllegalStateException(String.format("Environment variable GIT_SSH points to file %s but it doesn't exist.",
LambdaEnv.GIT_SSH_SCRIPT.getValue()));
}
JgitAccessor.clone(REPO_URI, CLONED_REPO_PATH);
} catch (IOException | DependencyFailureException e) {
log.info("Exception occurred while performing Service client integration. exception: [{}]", e.getMessage());
e.printStackTrace();
}
}
And this is the unit test class :
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.mockito.junit.MockitoJUnitRunner;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PowerMockIgnore;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
import static org.mockito.Mockito.*;
#RunWith(PowerMockRunner.class)
#PowerMockIgnore({"javax.management.*"})
#PrepareForTest({CreateTaskBuilder.class, LambdaEnv.class, ServiceAccessor.class, JgitAccessor.class})
public class CreateTaskBuilderTest extends TestUtils {
#Mock
private ServiceAccessor serviceAccessor;
#Mock
private JgitAccessor jgitAccessor;
#InjectMocks
CreateTaskBuilder builder;
#Before
public void setUp() {
MockitoAnnotations.initMocks(this);
}
#Test
public void loadServiceTicket_happyCase() throws Exception {
doNothing().when(serviceAccessor).loadTmpSshTicket();
PowerMockito.mockStatic(System.class);
Mockito.when(System.getenv("GIT_SSH")).thenReturn("/tmp/ssh.sh");
PowerMockito.mockStatic(Files.class);
Mockito.when(Files.exists(Paths.get("/tmp/ssh.sh"))).thenReturn(true);
PowerMockito.mockStatic(JgitAccessor.class);
PowerMockito.doNothing().when(JgitAccessor.class, "clone", Mockito.anyString(), Mockito.anyString());
builder.cloneRepository();
}
I am using Mockito = 2.28.x; PowerMockMockito = 2.x;

It looks like you have the wrong versions of libraries on your classpath.
The version of PowerMock you are using requires a Mockito with an org.mockito.MockingDetails.getMockHandler() which is not available in Mocktio 2.8.x. You can find it in a later version in 2.23.x.
Looking at minimum version dependencies for powermock-api-mockito2 version 2.0.0 you should be using mockito version 2.23.0 or later.
So looks like you need to update Mockito to a later version compatible with your PowerMock version, 2.23.x or later instead of 2.8.x.

Related

AEM Mockito unit testing issue

Since i am new to Mockito and AEM model java. I have a gone through some docs and wrote my first Mockito file for AEM Model java. In my code i've not see any errors, but while running i am not getting success and can't complete the code coverage 100%. Can anyone correct/help me to fix my code[given sample java with respective mockito file]
Java File:
import java.util.ArrayList;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.inject.Inject;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.resource.LoginException;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ValueMap;
import org.apache.sling.models.annotations.Model;
import org.apache.sling.models.annotations.injectorspecific.SlingObject;
import org.json.JSONException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.abc.cc.ddd.ResourceResolverService;
import com.abc.cc.ddd.services.models.bean.Accordion;
#Model(adaptables = SlingHttpServletRequest.class)
public class AccordionModel {
private final static Logger log = LoggerFactory.getLogger(AccordionModel.class);
#SlingObject
private SlingHttpServletRequest request;
#Inject
public ResourceResolverService resolverService;
private Resource resource;
public List < Accordion > accordionList = new ArrayList < Accordion > ();
#PostConstruct
protected void init() throws LoginException, JSONException {
log.info("AccordionModel init method Start");
resource = request.getResource();
final ValueMap configurationOptionProperties = resource.getValueMap();
log.debug("iconfigurationOptionProperties is " + configurationOptionProperties);
String count = configurationOptionProperties.get("count", String.class);
if (count != null) {
for (int i = 1; i <= Integer.valueOf(count); i++) {
Accordion accordion = new Accordion();
String title = configurationOptionProperties.get("title" + i, String.class);
String rte = configurationOptionProperties.get("rte" + i, String.class);
accordion.setTitle(title);
accordion.setRte(rte);
accordionList.add(accordion);
}
}
log.info("AccordionModel init method End");
}
public List < Accordion > getAccordionList() {
return accordionList;
}
}
Mockito code
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.when;
import java.util.ArrayList;
import java.util.List;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.resource.LoginException;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ValueMap;
import org.json.JSONException;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import com.abc.cc.ddd.ResourceResolverService;
import com.abc.cc.ddd.services.models.bean.Accordion;
#RunWith(MockitoJUnitRunner.class)
public class AccordionModelTest {
#InjectMocks
private AccordionModel accordionModel;
#Mock
Resource resource;
#Mock
SlingHttpServletRequest request;
#Mock
ResourceResolverService resourceResolverService;
#Mock
ValueMap valuemap;
public List < Accordion > accordionList = new ArrayList < Accordion > ();
String count = "6";
//max count, based on this count loop execute and get/set into the list
#Before
public void setUp() throws Exception {
when(request.getResource()).thenReturn(resource);
when(resource.getValueMap()).thenReturn(valuemap);
}
#Test
public void shouldReturnNullWhenPropertyIsNull() throws LoginException, JSONException {
when(valuemap.get("count", String.class)).thenReturn(null);
accordionModel.init();
assertEquals(accordionModel.getAccordionList(), null);
}
#Test
public void shouldReturnWhenPropertyNotNull() throws LoginException, JSONException {
when(valuemap.get("count", String.class)).thenReturn("count");
accordionModel.init();
assertEquals(accordionModel.getAccordionList(), count);
}
}
Errors in program its showing line--> accordionModel.init();
java.lang.NumberFormatException: For input string: "count"
at java.lang.NumberFormatException.forInputString(Unknown Source)
at java.lang.Integer.parseInt(Unknown Source)
at java.lang.Integer.valueOf(Unknown Source)
at com..services.sling.models.AccordionModel.init(AccordionModel.java:44) at
com..services.sling.models.AccordionModelTest.
shouldReturnWhenPropertyNotNull(AccordionModelTest.java:55)
java.lang.AssertionError: expected:<[]> but was:<null>
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)
at com..services.sling.models.AccordionModelTest.
shouldReturnNullWhenPropertyIsNull(AccordionModelTest.java:53)
java.lang.AssertionError: expected:<[]> but was:<null>
If you return null your list is empty. So adjust your test.
Consider renaming the method name as well.
If thats not what you want, you'll need to change your implementation.
#Test
public void shouldReturnNullWhenPropertyIsNull() throws LoginException, JSONException {
when(valuemap.get("count", String.class)).thenReturn(null);
accordionModel.init();
assertTrue(accordionModel.getAccordionList().isEmpty());
}
java.lang.NumberFormatException: For input string: "count"
"count" can not be converted into an Integer. Try using your count variable ("6") instead.
You should check the content of the list, for now I adjusted it to check that the list has the correct size.
#Test
public void shouldReturnWhenPropertyNotNull() throws LoginException, JSONException {
when(valuemap.get("count", String.class)).thenReturn(count);
accordionModel.init();
assertEquals(Integer.valueOf(count), accordionModel.getAccordionList().size());
}
Note that generally the parameter order for assert's should be expected vs actual.

Junit - Null Pointer Exception with #Before

I just started learning Junit and I just got Null Pointer Exception in my first test.
If I read correctly #Before annotation means it will be called before each test but looks like it doesn't or something else is wrong with this code. In this code below I get Null Pointer in myList.add() line.
import org.junit.Before;
import org.junit.jupiter.api.Test;
import java.util.ArrayList;
import java.util.List;
import static org.junit.Assert.*;
public class StudentTest {
private List<String> myList;
#Before
public void init(){
myList = new ArrayList<>();
}
#Test
public void size(){
myList.add("TEST");
assertEquals(1, myList.size());
}
}
The imports (jupiter) indicate you're using Junit5.
In JUnit5 you have to use the #BeforeEach annotation to indicate steps that have to be execute before each test method.
The #Before annotation was used in JUnit4.
I haven't tested this, just read the documentation https://junit.org/junit5/docs/current/user-guide/

Calling real method though given different answer to return on a static method execution

I am using power mockito and I am mocking a class SomeUtil having all static methods.
import java.util.List;
class SomeUtil {
// other static methods
public static X createX(String name, List<String> addresses, boolean isEnabled) {
// implementation
return null;
}
// other static methods
}
And I have mocked it as follows.
PowerMockito.mockStatic(SomeUtil.class, Answers.CALLS_REAL_METHODS.get());
Answer<Row> createXAnswer = new Answer<Row>() {
#Override
public Row answer(InvocationOnMock invocation) throws Throwable {
return new X();
}
};
PowerMockito.when(SomeUtil.createX(Mockito.any(String.class), Mockito.any(List.class), Mockito.any(Boolean.class)).thenAnswer(createXAnswer);
But with that createX() method always invokes original method, which I am trying to avoid. I suspect that because of boolean primitive type. Am I missing something here? Please guide
I think you have omitted some important annotations on your test class (#RunWithand #PrepareForTest). This is a complete example:
import static org.junit.Assert.assertSame;
import static org.mockito.Matchers.anyBoolean;
import static org.mockito.Matchers.anyList;
import static org.mockito.Matchers.anyString;
import static org.powermock.api.mockito.PowerMockito.mockStatic;
import static org.powermock.api.mockito.PowerMockito.when;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
#RunWith(PowerMockRunner.class)
#PrepareForTest(SomeUtil.class)
public class SomeUtilTest {
#Test
public void should_do_this() {
mockStatic(SomeUtil.class, Mockito.CALLS_REAL_METHODS);
final X x = new X();
when(SomeUtil.createX(anyString(), anyList(), anyBoolean())).thenReturn(x);
assertSame(x, SomeUtil.createX(null, null, true));
}
}
This example works but could in some case. For example if the createX raise an exception. fail sometime because the **real method createX is invoked ** * when we stub it:
when(SomeUtil.createX(anyString(), anyList(), anyBoolean())).thenAnswer(createXAnswer);
this is due to the default answer CALLS_REAL_METHODS:
mockStatic(SomeUtil.class, Mockito.CALLS_REAL_METHODS);
since the OP can't remove this default answer (see comment):
For only few methods I want to return our own Answer. For the rest of methods I want to call real methods.
I think you will have to use powermock api:
import static org.junit.Assert.assertSame;
import static org.powermock.api.mockito.PowerMockito.mockStatic;
import static org.powermock.api.support.membermodification.MemberMatcher.method;
import static org.powermock.api.support.membermodification.MemberModifier.stub;
import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
#RunWith(PowerMockRunner.class)
#PrepareForTest(SomeUtil.class)
public class SomeUtilTest {
#Test
public void should_do_this() {
mockStatic(SomeUtil.class, Mockito.CALLS_REAL_METHODS);
final X x = new X();
stub(method(SomeUtil.class,
"createX",
String.class,
List.class,
boolean.class)).toReturn(x);
assertSame(x, SomeUtil.createX(null, null, true));
}
}

What is the best way of replace CXF's JSONProvider (Jettison based) with MOXy?

I was wondering why MOXy is not providing a JSONProvider class similar to JACKSON to replace the default JSON provider in a jax-rs implementation?
This would be the easiest way to deal with all classes in a certain package.
What I ended up doing was to do the following as I feel that custom context resolver or MessageBodyWriter/Reader are mostly suited to handle certain classes, but not to handle all classes in a package especially if you have many classes.
Am I right?
What are your thoughts?
What is the best way to replace Jettison with MOXy in CXF to handle all classes in a package?
import java.io.IOException;
import java.io.OutputStream;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import org.apache.cxf.jaxrs.provider.json.JSONProvider;
import org.eclipse.persistence.jaxb.MarshallerProperties;
import org.eclipse.persistence.jaxb.JAXBContextFactory;
public class MyJSONProvider<T> extends JSONProvider<T> {
private static JAXBContext jaxbContext = null;
static {
try {
jaxbContext = JAXBContextFactory.createContext("com.bp.bs", null);
} catch (JAXBException jaxbe) {
jaxbe.printStackTrace();
throw new ExceptionInInitializerError(jaxbe);
}
}
#Override
public void writeTo(T obj, Class<?> cls, Type genericType,
Annotation[] anns, MediaType m,
MultivaluedMap<String, Object> headers, OutputStream os)
throws IOException, WebApplicationException {
Marshaller marshaller = null;
try {
marshaller = jaxbContext.createMarshaller();
marshaller.setProperty(MarshallerProperties.MEDIA_TYPE,
"application/json");
marshaller.setProperty(MarshallerProperties.JSON_INCLUDE_ROOT, false);
marshaller.marshal(obj, os);
} catch (JAXBException jaxbe) {
jaxbe.printStackTrace();
}
}
}
EclipseLink JAXB (MOXy) offers the org.eclipse.persistence.jaxb.rs.MOXyJsonProvider class that can be used to enable it as the JSON-provider.
Below is an example of a JAX-RS Application class that configures MOXyJsonProvider.
package org.example;
import java.util.*;
import javax.ws.rs.core.Application;
import org.eclipse.persistence.jaxb.rs.MOXyJsonProvider;
public class CustomerApplication extends Application {
#Override
public Set<Class<?>> getClasses() {
HashSet<Class<?>> set = new HashSet<Class<?>>(2);
set.add(MOXyJsonProvider.class);
set.add(CustomerService.class);
return set;
}
}
MOXyJsonProvider was added in EclipseLink 2.4.0. The latest version is EclipseLink 2.4.1 which can be downloaded from the following link:
http://www.eclipse.org/eclipselink/downloads/
For More Information
http://blog.bdoughan.com/2012/05/moxy-as-your-jax-rs-json-provider.html

How to test #Valid

In my entities I have some hibernate annotations for validation, like #NotEmpty, #Pattern.. and others
In my controller, on save action, it has an #Valid parameter.
But if any entity has any required field, and there is no annotation I will have problems.
So I would like to test each entity, to ensure they have the necessary notes.
Something like:
#Test(expect=IllegalArgumentException.class)
public void testAllNull() {
Person p = new Persson(); // Person name has an #NotEmpty
validator.validate(p);
}
But how to validate it? Who is called to check #Valid?
Thanks.
I found out how to check:
#Autowired
private LocalValidatorFactoryBean validator;
...
validator.validateProperty(object, propertyName)
Here is a Spring v4.1.x based example of a test validating presence and processing of the #Valid annotation and building of custom JSON response in case of an error.
jUnit
import com.fasterxml.jackson.core.type.TypeReference;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.context.annotation.Bean;
import org.springframework.http.MediaType;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import javax.inject.Inject;
import java.util.List;
import static org.abtechbit.miscboard.util.JsonUtils.toJson;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.junit.Assert.assertThat;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes = {
RegistrationValidationTest.MockDependencies.class,
})
public class RegistrationValidationTest {
#Inject
MockMvc mvc;
#Test
public void validatesRegistration() throws Exception {
Registration registration = ... //build an invalid Registration object
MvcResult result = mvc.perform(post(RegistrationController.CONTEXT_REGISTER).
contentType(MediaType.APPLICATION_JSON).
content(toJson(registration))).
andExpect(status().isBadRequest()).
andExpect(content().contentType(MediaType.APPLICATION_JSON)).
andReturn();
assertThat(result.getResolvedException(), is(notNullValue()));
String content = result.getResponse().getContentAsString();
assertThat(content, is(notNullValue()));
List<Message> messages = JsonUtils.fromJson(content, new TypeReference<List<Message>>() {
});
assertThat(messages.size(), is(1));
}
public static class MockDependencies {
#Bean
public MockMvc mvc() {
return MockMvcBuilders.standaloneSetup(new RegistrationController()).build();
}
}
}
Controller
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
import java.util.List;
import java.util.stream.Collectors;
#Controller
public class RegistrationController
{
public static final String CONTEXT_REGISTER = "/register";
#RequestMapping(value = CONTEXT_REGISTER, method = RequestMethod.POST)
#ResponseBody
public String register(#RequestBody #Valid Registration registration) {
//perform registration
}
#ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<List> handleValidationException(MethodArgumentNotValidException ex) {
//Build a list of custom Message{String message;} objects
List<Message> messages = ex.getBindingResult().getAllErrors().
stream().map(e->new Message(e.getDefaultMessage())).collect(Collectors.toList());
return ResponseEntity.status(HttpStatus.BAD_REQUEST).contentType(MediaType.APPLICATION_JSON).body(messages);
}
}
Spring MVC Test Framework might be a good choice. By using this, you can be assured that validations in your tests runs codes as Spring #MVC actually works.
Actually, the #Valid annotation is detected by HandlerMethodInvoker, which processes annotations on the handler methods of Spring controllers. Internally, the actual validation logic is delegated to the Validator bean depending on your application context settings. (Hibernate Validator is widely used.)
By default configuration (e.g. <mvc:annotation-driven />), LocalValidatorFactoryBean is used internally to process #Valid annotation as #Falci noted, but it may differ time to time. Instead, Spring MVC Test Framework provides the same environment as the main application uses, hence a good choice.