How to mock a method which takes Class as parameter - junit

I can mock a method like printMyValue(String value);
like
when(myClass.printMyValue(anyString())then return "Some value";
But how can i mock printMyValue(MyClass value);

You can use the "any" method. You just can't statically import it. Your code will look something like this:
package jtsandbox;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import org.junit.Test;
import org.mockito.Mockito;
/**
* Explains mocking question from http://stackoverflow.com/questions/29392623/how-to-mock-a-method-which-takes-class-as-parameter/29393040#29393040
* #author Jason W. Thompson (https://plus.google.com/+JasonWThompson_SoftwareDeveloper)
*/
public class TestStuff
{
/**
* Tests mocking
* #throws Exception An exception is not expected to be thrown
*/
#Test
public void testmethod() throws Exception
{
// Given
final Foo mockFoo = mock(Foo.class);
when(mockFoo.printMyValue(Mockito.<Class<?>>any())).thenReturn("Hi!");
// When
final String answer = mockFoo.printMyValue(String.class);
// Then
assertThat(answer, is("Hi!"));
}
public interface Foo
{
public String printMyValue(Class<?> clazz);
}
}

You can use Mockito's any matcher:
when(myClass.printMyValue(any(MyClass.class)).thenReturn("Some value");

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.

How to create mock instance of Autowired component in Vert.x

I am trying to create mock instance of the class which is autowired inside Verticle but I am getting it as a null. For synchronous code the way which works is looking not useful for Vert.x.
Verticle is:
#Component
public class MyVerticle extends AbstractVerticle{
#Autowired
private ServiceExecutor serviceExecutor;
#Override
public void start() throws Exception {
super.start();
vertx.eventBus().<String>consumer("address.xyz").handler(handleRequest());
}
private Handler<Message<String>> handleRequest() {
return msg -> {
getSomeData(msg.body().toString())
.setHandler(ar -> {
if(ar.succeeded()){
msg.reply(ar.result());
}else{
msg.reply(ar.cause().getMessage());
}
});
};
}
private Future<String> getSomeData(String inputJson) {
Promise<String> promise = Promise.promise();
String data = serviceExecutor.executeSomeService(inputJson); // Getting NPE here. serviceExecutor is coming as null when trying to create mock of it using Mockito.when.
promise.complete(data);
return promise.future();
}
}
Dependent component is:
#Component
public class ServiceExecutor {
public String executeSomeService(String input){
return "Returning Data";
}
}
Test case is:
import static org.mockito.Mockito.when;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import io.vertx.core.Vertx;
import io.vertx.ext.unit.Async;
import io.vertx.ext.unit.TestContext;
import io.vertx.ext.unit.junit.VertxUnitRunner;
#RunWith(VertxUnitRunner.class)
public class MyVerticleTest {
#Mock
private ServiceExecutor serviceExecutor;
private Vertx vertx;
#Before
public void setup(TestContext ctx){
MockitoAnnotations.initMocks(this);
Async async = ctx.async();
this.vertx = Vertx.vertx();
vertx.deployVerticle(MyVerticle.class.getName(), h -> {
if(h.succeeded()){
async.complete();
}else{
ctx.fail();
}
});
}
#Test
public void test_consumption(TestContext ctx) {
Async async = ctx.async();
when(serviceExecutor.executeSomeService(Mockito.anyString())).thenReturn("Returning Data");
vertx.eventBus().request("address.xyz","message", h ->{
if(h.succeeded()){
ctx.assertEquals("Returning Data",h.result().body().toString());
async.complete();
}else{
ctx.fail(h.cause());
}
});
}
}
Above Test Case works well if I don't use autowired instance to call a method to get the date. But if used it (which I must do to get the data), it is giving NPE at MyVerticle->getSomeData() method when trying to use serviceExecutor object as a mock. This approach works very well for Synchronous code flow but for Vert.x looks like it won't help. So need help here to mock the autowired instance serviceExecutor inside Verticle.
Add a constructor in your MyVerticle
public MyVerticle(ApplicationContext context) {
context.getAutowireCapableBeanFactory().autowireBean(this);
}
and deploy your verticle something like vertx.deployVerticle(new MyVerticle(context),...
I have application context while deploying the verticle and thats what I am passing in the constructor. Check if this works for you.

How do I mock a static method call from a nother static method in the same class?

I have a utilities class wherein one static method calls another. I want to mock the called method but not the target method. Does anyone have an example?
I've got:
#RunWith(PowerMockRunner.class)
#PrepareForTest({SubjectUnderTest.class})
public class SubjectUnderTestTest {
...
SubjectUnderTest testTarget = PowerMockito.mock(SubjectUnderTest.class, Mockito.CALLS_REAL_METHODS);
Starting from the docs, with some minor tweaks, you can either mock or spy the static method, depending on what you need (spying seems a bit less verbose but has different syntax). You can find below a sample for both, based on PowerMockito 1.7.3 & Mockito 1.10.19.
Given the following simple class with the required 2 static methods:
public class ClassWithStaticMethods {
public static String doSomething() {
throw new UnsupportedOperationException("Nope!");
}
public static String callDoSomething() {
return doSomething();
}
}
You can do something like:
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
import static org.powermock.api.mockito.PowerMockito.*;
// prep for the magic show
#RunWith(PowerMockRunner.class)
#PrepareForTest(ClassWithStaticMethods.class)
public class ClassWithStaticMethodsTest {
#Test
public void shouldMockStaticMethod() {
// enable static mocking
mockStatic(ClassWithStaticMethods.class);
// mock the desired method
when(ClassWithStaticMethods.doSomething()).thenReturn("Did something!");
// can't use Mockito.CALLS_REAL_METHODS, so work around it
when(ClassWithStaticMethods.callDoSomething()).thenCallRealMethod();
// validate results
assertThat(ClassWithStaticMethods.callDoSomething(), is("Did something!"));
}
#Test
public void shouldSpyStaticMethod() throws Exception {
// enable static spying
spy(ClassWithStaticMethods.class);
// mock the desired method - pay attention to the different syntax
doReturn("Did something!").when(ClassWithStaticMethods.class, "doSomething");
// validate
assertThat(ClassWithStaticMethods.callDoSomething(), is("Did something!"));
}
}

How to overcome "Conflicting setter definitions for property "?

I use com.fasterxml.jackson and io.swagger libraries. In my REST endpoint I use org.javamoney.moneta.Money type for a GET query. When deploying the war i get following exception 1;
I have followed this reference and wrote following code[2]; and registered it at #ApplicationPath. But still getting same issue.
Any guide would be really helpful?
#ApplicationPath("/rest")
public class RestApplication extends Application {
#Override
public Set<Class<?>> getClasses() {
HashSet<Class<?>> set = new HashSet<Class<?>>();
set.add(com.test.JsonMoneyProvider.class);
[2]
import javax.money.CurrencyUnit;
import javax.money.Monetary;
import javax.money.MonetaryAmountFactory;
import javax.ws.rs.ext.Provider;
import javax.xml.bind.annotation.XmlTransient;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider;
#Provider
public class JsonMoneyProvider extends JacksonJsonProvider {
public JsonMoneyProvider() {
ObjectMapper mapper = new ObjectMapper();
mapper.addMixIn(MonetaryAmountFactory.class, MixIn.class);
setMapper(mapper);
}
public static interface MixIn {
#JsonIgnore
#XmlTransient
MonetaryAmountFactory setCurrency(CurrencyUnit currency);
#JsonIgnore
#XmlTransient
default MonetaryAmountFactory setCurrency(String currencyCode) {
return setCurrency(Monetary.getCurrency(currencyCode));
}
}
}
1
Caused by: java.lang.IllegalArgumentException: Conflicting setter definitions for property "currency": javax.money.MonetaryAmountFactory#setCurrency(1 params) vs javax.money.MonetaryAmountFactory#setCurrency(1 params)
at com.fasterxml.jackson.databind.introspect.POJOPropertyBuilder.getSetter(POJOPropertyBuilder.java:293)
at io.swagger.jackson.ModelResolver.resolve(ModelResolver.java:246)
at io.swagger.jackson.ModelResolver.resolve(ModelResolver.java:127)
at io.swagger.converter.ModelConverterContextImpl.resolve(ModelConverterContextImpl.java:99)
at io.swagger.jackson.ModelResolver.resolveProperty(ModelResolver.java:106)
a
Simply use this annotation on the deserialization setter method to indicate Jackson wich one to use: #com.fasterxml.jackson.annotation.JsonSetter

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));
}
}