I am trying to update the junit by passing an object but I am getting "Arguments are different error"
Here is my code:
I updated the existing dataController, dataService
DataController:
old method:
List<String> clientData= dataService .retrieveClientData(user, Clientroperties.product);
updated to:
dataIdCollector dataIdCollector = new dataIdCollector();
List<String> clientData= dataService .retrieveClientData(user, Clientroperties.product, dataIdCollector);
Here is the dataService class
DataService:
List<String> clientData retrieveClientData(user, Clientroperties.product, dataIdCollector){
List<ClientDetails> details = dataDao.getDetails(user, Clientroperties.product);
dataIdCollector.collectIds(details);
return serailizeClientDetails(details);
}
I was trying to update the junit by passing dataIdCollector object
dataIdCollector dataIdCollector = new dataIdCollector();
when(mockService.retrieveClientData(user, Clientroperties.product, dataIdCollector))
.thenReturn(Arrays.asList("abc"));
String result = this.mockMvc.perform(
get("/rest" + RestApiRequestMapping.clientData)
.with(credentials)
.accept(MediaType.APPLICATION_JSON)
)
.andExpect(status().isOk())
.andReturn().getResponse().getContentAsString();
verify(mockService).retrieveClientData(user, Clientroperties.product,dataIdCollector);
here mockMVC endpoint is calling a method in dataController .The dataIdCollector object again created in controller class and causing "Arguments are different " error.
how to fix this issue in junit?
Argument(s) are different!Wanted:
dataIdCollector#1fb71788
Actual invocations have different arguments:
dataIdCollector#8cb7185
the mockservice is not updating dataIdCollector object,why it is still getting "different argument.." error.
Related
For mocking local variable/method call on local object that is constructed inside method under test, we are using PowerMockito library as of now.
We are trying to evaluate whether we can use mockito-inline (version 3.7.7) to do the same.
In short, we are trying to intercept construction of object using Mockito.mockConstruction, so that we can specify mocked behavior on object created locally.
Here is a scenario which describes our usage. Since this is legacy code, we are not in a position to change it now.(e.g. Change dependency to instance variable or some other refactoring)
In short, execute() method of class MyClass is constructing object of Util class locally. Since we want to unit test core logic of execute() & hence need to mock process() method called on local Util object created inside execute() method of class MyClass.
public class MyClass {
public String execute(){
Util localUtil = new Util();
String data = localUtil.process();
//Core logic of the execute() method that needs to be unit tested...
//Further update data based on logic define in process() method.
data = data + " core logic";
return data;
}
}
public class Util {
public String process(){
String result = "real";
//Use various other objects to arrive at result
return result;
}
}
#Test
public void testLocalVar(){
Util util = new Util();
Assertions.assertEquals("real", util.process());
try (MockedConstruction<Util> mockedConstruction = Mockito.mockConstruction(Util.class);) {
util = new Util();
when(util.process()).thenReturn("mocked method data");
String actualData = util.process();
//This works on local object created here.
Assertions.assertEquals("mocked method data",actualData);
//Object,method under test
MyClass myClass = new MyClass();
actualData = myClass.execute();
//This doesn't not works on local object created inside method under test
Assertions.assertEquals("mocked method data" + " core logic",actualData); //Fails
}
}
Here we are able to define mocked behavior on method on object created locally inside test method. But same thing is not possible with local object created inside actual method under test.
I can see mockedConstruction.constructed() does have every object of class created
But not able to specify mocked behavior on on localUtil.process() inside execute() method ..
Any suggestions..
In your case, you have to stub the behavior when instructing Mockito to mock the constructor. The Mockito.mockConstruction() is overloaded and allows to not only pass the class you want to mock the constructor for:
#Test
void mockObjectConstruction() {
try (MockedConstruction<Util> mocked = Mockito.mockConstruction(Util.class,
(mock, context) -> {
// further stubbings ...
when(mock.process()).thenReturn("mocked method data");
})) {
MyClass myClass = new MyClass();
actualData = myClass.execute();
}
}
You can find further possible stubbing scenarios in this article.
How can I mock the custom util class? I am getting the error below:
[ERROR] 2019-08-20 12:06:02:197 [] com.metlife.api.clientlibrary.util.JWSRequestUtil.prepareRequestJWS():71 - Exception in preparing JWS request ::
java.lang.NullPointerException: null
The code is:
public class EPartnerPromotionHelperTest {
#InjectMocks
EPartnerPromotionHelper ePartnerPromotionHelper;
#Mock
private JWSRequestUtil jwsRequestUtil;
#Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
}
#Test
public void testSavePromotion() throws Exception {
String loggerId = "loggerId";
PromotionDTO promotionDTO = new PromotionDTO();
promotionDTO.setDescription("description");
promotionDTO.setCreationDate(new Date());
promotionDTO.setModifiedDate(new Date());
Mockito.when(jwsRequestUtil.prepareRequestJWS(Matchers.any(EPartnerRestRequestDTO.class)
,Matchers.any(Boolean.class))).thenReturn("test");
PromotionDTO response =ePartnerPromotionHelper.savePromotion(loggerId,promotionDTO);
assertNotNull(response);
}
}
Assuming that the error message comes from the invocation of your prepareRequestJWS method, you can change your syntax and use doReturn instead.
Mockito.doReturn("test")
.when(jwsRequestUtil)
.prepareRequestJWS(Matchers.any(EPartnerRestRequestDTO.class),
Matchers.any(Boolean.class));
Writing it like this the prepareRequestJWS method won't be invoked, check the Overriding a previous exception-stubbing part that is described in the javadoc of the doReturn method. This also applies to normal methods that would throw Exception's when they are invoked.
However a question would be why this exception is coming from your JwsRequestUtil class in the first place. Feel free to add the relevant code to your question.
I am using primefaces version 5 and I am adding messages regarding to a specific actions like save :
public void save(Tenant tenant) {
tenantDao.save(tenant);
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage("Save success"));
}
Since I had a lot of these actions I tried to simplify this by creating a custom annotation called Message:
#Target(Runtime)
#Retention(Method)
public #interface Message {
String value();
}
and in my dao class :
public class TenantDao {
#Message("Saved Successfully")
public Tenant save(Tenant t) {
return em.save(t);
}
}
To read this annotation I have overridden the ELResolver the method invoke
public Object invoke(ELContext context,
Object base,
Object method,
Class<?>[] paramTypes,
Object[] params) {
Object result = super.invoke(context,method,paramTypes,params);
Method m = base.getClass().getMethod(method,paramTypes);
if(m.getAnnotation(Message.class) != null) {
addMessahe(m.getAnnotation(Message.class).value());
}
return result;
}
This was called in property (rendered, update, ..) but not in action listener
After a lot of debugging I discovered that theactionListener is called from MethodExpression class. So, I wrapped the MethodExpression class, and override the method invoke.
The problem now is that there are no way to retreive the class Method from MethodExpression class, also if I used the expression #{tenantDao.save(tenant)} the method getMethodInfo from MethodExpression will throw an exception.
Are there any way to read tAnnotation from any jsf context ?
I know that using Spring with AOP may solve this but I am not using Spring now.
Thanks
I have two classes to try to figure out how whenNew works.
public class RockService {
public RockData serv() {
RockData rockData = new RockData();
rockData.setName("RockService");
rockData.setContent("content from rock service");
return rockData;
} }
And
public class RockData {
String name;
long id;
String content;
// get set method ignored
}
With test code
#RunWith(PowerMockRunner.class)
#PrepareForTest(RockService.class)
public class MockNewInstanceCreation {
#Test
public void mockCreationTest() throws Exception {
RockData rockData = mock(RockData.class);
when(rockData.getName()).thenReturn("this is mock");
whenNew(RockData.class).withNoArguments().thenReturn(rockData);
RockService rockService = new RockService();
RockData servData = rockService.serv();
System.out.println(servData.getName());
System.out.println(servData.getContent());
}
}
So at runtime, if not mock, the output (RockData's getName()) would be "RockService". But with mock, it returns "this is mock". The code works but still I didn't know how exactly Powermock/Mockito did this.
I debugged the code. What confused me is after RockData rockData = new RockData(); executed, what actually created is exactly the instance that created by RockData rockData = mock(RockData.class);. Which means new RockData() doesn't create an new instance at all. It just returned an instance that already created. And when debugging, it jumped to MockGateway.newInstanceCall.
So how does Powermockito intercept new instance?
PowerMockRunner runs tests using special class loader - org.powermock.core.classloader.MockClassLoader.
Instead of loading real class it loads a new one with the same signature. It means that the real constructor won't be invoked.
So the object that is returned by new operator is not a Mock. It is a instance of a different class that could be assigned to the real one and it returns mocked values.
See the code below:
public class RockService {
ClassLoader classLoader = this.getClass().getClassLoader();
System.out.println("Real construct");
//Different class loader
System.out.println(classLoader);
//The same class
System.out.println(this.getClass());
}
public RockData serv() {
RockData rockData = new RockData();
Class<? extends RockData> clazz = rockData.getClass();
//This is a different class
System.out.println("Mocked class: " + clazz.getCanonicalName());
//And different classloader
ClassLoader classLoader = clazz.getClassLoader();
System.out.println(classLoader);
//Mocked class instance could be assigned to real one
System.out.println(RockData.class.isAssignableFrom(clazz));
//it's instance of both RockData.class and mocked class
System.out.println(clazz.isInstance(rockData));
System.out.println(RockData.class.isInstance(rockData));
rockData.setName("RockService");
rockData.setContent("content from rock service");
return rockData;
}
In this code, i have mocked the one of the ValidateHandlerSoapClient class method which is instantiated and called this method (soapClientSpy.processSoapRequestRespons) in validateMsisdnHandlerIRSpy.validate().So soapClientSpy.processSoapRequestResponse is not working , instead the real method is called.
#RunWith(PowerMockRunner.class)
#PrepareForTest({ValidateMsisdnHandler.class,ValidateHandlerSoapClient.class})
public class Demo {
MessageControl messageControl=PowerMockito.mock(MessageControl.class);
Validate validate=PowerMockito.mock(Validate.class);
ValidateMsisdnHandlerIR validateMsisdnHandlerIRSpy = PowerMockito.spy(new ValidateMsisdnHandlerIR());
ValidateHandlerSoapClient soapClientSpy = PowerMockito.spy( new ValidateHandlerSoapClient());
#Before
public void initialize() throws Exception
{
PowerMockito.when(validate.getAccountId()).thenReturn("0879221485");
PowerMockito.doReturn(true).when(validateMsisdnHandlerIRSpy, "isPrePaid",anyString());
MemberModifier.field( ValidateMsisdnHandlerIR.class, "endDate").set(
validateMsisdnHandlerIRSpy, "10-FEB-2015");
PowerMockito.when(soapClientSpy.processSoapRequestResponse(anyString())).thenReturn(true);
PowerMockito.whenNew(ValidateHandlerSoapClient.class).withNoArguments().thenReturn(soapClientSpy);
}
#Test
public void testValidateMsisdn_Cr6_Roverprempay_Not_Roverpayg() throws Exception{
Response response = validateMsisdnHandlerIRSpy.validate(validate,messageControl);
}
Replace
ValidateHandlerSoapClient soapClientSpy = PowerMockito.spy( new ValidateHandlerSoapClient())
with
ValidateHandlerSoapClient soapClientMock = PowerMockito.mock(ValidateHandlerSoapClient.class)
A spy by default just calls the methods of the underlying regular class. What you want to do is (presumably) nothing when the methods of the soap client are called.
Then of course you will need to make also change:
PowerMockito.whenNew(ValidateHandlerSoapClient.class).withNoArguments().thenReturn(soapClientMock);