SOAP with MockitoJUnit is not working in java - java

#WebService(name = "ManageSearchDataPortType", targetNamespace = "https://abc/searchData", serviceName = "ManageSearchData", portName = "ManageSearchDataPort", wsdlLocation = "/WEB-INF/wsdl/ManageSearchData.wsdl")
#SOAPBinding(parameterStyle = SOAPBinding.ParameterStyle.BARE)
import com.xyz.SearchDataRequest;
import com.xyz.SearchDataResponse;
#XmlSeeAlso({ ObjectFactory.class, com.abc.ObjectFactory.class, com.abc..ObjectFactory.class, com.abc..ObjectFactory.class })
public class ManageSearchDataService {
#WebResult(name = "searchDataResponse", partName = "searchDataResponse", targetNamespace = "https://abc/searchData")
#WebMethod(action = "http://example.com/wsdl/ManageABC/2008/10/22#searchData")
public SearchDataResponse searchData(#WebParam(name = "searchDataRequest", partName = "searchDataRequest", targetNamespace = "https://abc/searchData")
SearchDataRequest searchDataRequest) {
System.out.println(" searchData Methodthod");
}
public void test();
{
System.out.println("TEST Method");
}
}
Below is my junit mockito test class contains the test method i.e doSomething. Here i'm trying to mack ManageSearchDataService class which shown above contains searchData and test method, But
searchData not being called by mock object
and normal test method has been called successfully.
searchData is my WebMethod as you can see the method.
HeaderClass is just normal call which contains getMPLNHeader static method.
Please anyone have any idea how to do this let me know.
package com.test;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import com.xyz.SearchDataRequest;
import com.aaa.ManageSearchDataService;
#RunWith(MockitoJUnitRunner.class)
public class JunitTestClass {
#Mock ManageSearchDataService mockObj ;
#Test
public void doSomething() {
SearchDataRequest searchDataRequest= new SearchDataRequest();
searchDataRequest.setStandardHeader(HeaderClass.getMPLNHeader("ASV"));
mockObj.searchData(searchDataRequest); // not Working
mockObj.test(); // this working fine printing data
}
}

You should not mock the class you want to test. You mock all other classes/objects except the class you want to test.

As people already pointed out, mocking ManageSearchDataService doesn't make any sense. You are creating a mock object of your service and then test that mock, this isn't telling you anything about your service. Mocking is for dependencies, for example, if your service used another object to load data from a database, then mocking this would be a great idea for a unit test (because otherwise, your test would fail if the DB is down - even if the code it completely ok).
Mocking allows you to test one single unit by "simulating" all of its dependencies, so you don't have to rely on them being ok (that's the problem of other unit tests), because you simulate it in a way as if they were ok (or not, if you want to test error handling in your unit).
Since your class does not contain any dependencies like this at all (it doesn't actually do anything besides printing) there is nothing you could or should mock here.

Related

How to create a test for a custom ParameterResolver implementation?

I've created a ParameterResolver implementation in order to inject a parameter into my test methods.
I have a scenario where the instantiation of the parameter object could fail without some proper parameters defined by the correspondent annotation and an exception is thrown.
#TestScenario(homeDirName = "")
#Test
void ensureFailingWithoutProperHomeDirectory(LauncherRuntime launcher) {
assertThrows(MissingPropertiesException.class,
() -> launcher.run());
}
But this test is failing even before starting to run, with a ParameterResolutionException.
I would like to know how can I test it.
Since you want to test your ParameterResolver implementation and not the JUnit engine the entry point of your Unit test should be the provideArguments method of your implementation. JUnit catches every exception that is thrown by this method and adds it as cause for a new ParameterResolutionException. There are two possible approaches:
A)
If your implementation should call multiple methods of ExtensionContext then mock these methods together with your annotation. And call the provideArguments of your implementation.
B)
If your implementation should use the ExtensionContext only to get the annotation and does nothing more with it that is worth for testing, then move main functionality into an own method (e.g. accept(MyAnnotation)) and test this method. See for example here how the JUnit developers to this for the CVSSource annotation.
Here's an example test case for my ResourceFilesArgumentsProvider / ResourceFilesSource annotation:
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
class ResourceFilesArgumentsProviderTest {
#Test
public void nonExistingDirectory() throws Exception {
ResourceFilesSource annotation = resourceFiles("/non-existing-dir");
AnnotatedElement annotatedElement = mock(AnnotatedElement.class);
when(annotatedElement.getAnnotation(ResourceFilesSource.class))
.thenReturn(annotation);
ExtensionContext context = mock(ExtensionContext.class);
when(context.getElement()).thenReturn(Optional.of(annotatedElement));
when(context.getTestClass()).thenReturn(Optional.of(getClass()));
assertThrows(NoSuchFileException.class, () -> provideArguments(context));
}
private Stream<Object[]> provideArguments(ExtensionContext context) throws Exception {
ResourceFilesArgumentsProvider provider = new ResourceFilesArgumentsProvider();
return provider.provideArguments(context).map(Arguments::get);
}
private ResourceFilesSource resourceFiles(String directory) {
/* mock the annotation with Mockito, or alternatively create
* an anonymous class with new ResourceFileSource() { ... }
*/
ResourceFilesSource annotation = mock(ResourceFilesSource.class);
when(annotation.directory()).thenReturn(directory);
return annotation;
}
}

java: unit test lambda expression inside dispatcher

I have a class:
public class RequestHandler implements HttpHandler {
public void handleRequest(HttpServerExchange serverContext) throws Exception {
serverContext.dispatch(() -> serverContext.getRequestReceiver()
.receiveFullBytes((httpServerExchange, reqBytes) -> {
// business logic along with few function call
}
)
);
}
}
I want to write a unit test case to test my business logic. I am not sure how to do it with 2 levels of a lambda expression insider a dispatcher? Can someone please suggest a good way to write test cases?
I know that we can move business logic to new class and can test it (i guess it's better designed) but curious to know what if it's part of some legacy code or something that we can't change, how can we test it?
Under the assumption that somewhere in your buisness logic you forward the received message (or whatever you do with it) to somewhere else, you can just test your code as usual.
Note that HttpServerExchange is a final class, so you need to use a Mockito version that supports final mocking - and you have to enable it, as described here.
To get around the lambda expression you need to use thenAnswer or doAnswer to trigger the invocation of the correct interface method manually.
A simple example could look like this:
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.ArgumentCaptor;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension;
import org.mockito.stubbing.Answer;
import io.undertow.io.Receiver;
import io.undertow.io.Receiver.FullBytesCallback;
import io.undertow.server.HttpHandler;
import io.undertow.server.HttpServerExchange;
#ExtendWith(MockitoExtension.class)
public class RequestHandlerTest {
static class BuisnessLogic {
public void someMethod(HttpServerExchange httpServerExchange, byte[] reqBytes) {
}
}
static class RequestHandler implements HttpHandler {
BuisnessLogic logic;
public void handleRequest(HttpServerExchange serverContext) throws Exception {
serverContext.dispatch(
() -> serverContext.getRequestReceiver().receiveFullBytes(
(httpServerExchange, reqBytes) -> {
logic.someMethod(httpServerExchange, reqBytes);
}
)
);
}
}
#Mock
BuisnessLogic logic;
#InjectMocks
RequestHandler handler;
#Test
public void test() throws Exception {
byte[] message = new byte[] {1,2,3};
HttpServerExchange serverContext = Mockito.mock(HttpServerExchange.class);
// 1st lambda
Mockito.when(serverContext.dispatch(Mockito.any(Runnable.class)))
.thenAnswer((Answer<HttpServerExchange>) invocation -> {
Runnable runnable = invocation.getArgument(0);
runnable.run();
return serverContext;
});
// 2nd lambda
Receiver receiver = Mockito.mock(Receiver.class);
Mockito.doAnswer((Answer<Void>) invocation -> {
FullBytesCallback callback = invocation.getArgument(0);
callback.handle(serverContext, message);
return null;
}).when(receiver).receiveFullBytes(Mockito.any(FullBytesCallback.class));
Mockito.when(serverContext.getRequestReceiver()).thenReturn(receiver);
// class under test - method invocation
handler.handleRequest(serverContext);
// buisness logic call verification
ArgumentCaptor<HttpServerExchange> captor1 = ArgumentCaptor.forClass(HttpServerExchange.class);
ArgumentCaptor<byte[]> captor2 = ArgumentCaptor.forClass(byte[].class);
Mockito.verify(logic).someMethod(captor1.capture(), captor2.capture());
Assertions.assertEquals(serverContext, captor1.getValue());
Assertions.assertEquals(message, captor2.getValue());
}
}
As others already mentioned you should only use that approach for legacy code.
A simple refactoring could just push the entire part you need to test into its own method, which - in the example above - would just be the buisness logic itself.
There is no explicit need to test the undertow framework yourself.

Mockito: Mock private field initialization

How I can mock a field variable which is being initialized inline?
class Test {
private Person person = new Person();
...
public void testMethod() {
person.someMethod();
...
}
}
Here I want to mock person.someMethod() while testing the Test.testMethod() method for which I need to mock initialization of person variable. Any clue?
Edit: I'm not allowed to modify Person class.
Mockito comes with a helper class to save you some reflection boiler plate code:
import org.mockito.internal.util.reflection.Whitebox;
//...
#Mock
private Person mockedPerson;
private Test underTest;
// ...
#Test
public void testMethod() {
Whitebox.setInternalState(underTest, "person", mockedPerson);
// ...
}
Update:
Unfortunately the mockito team decided to remove the class in Mockito 2. So you are back to writing your own reflection boilerplate code, use another library (e.g. Apache Commons Lang), or simply pilfer the Whitebox class (it is MIT licensed).
Update 2:
JUnit 5 comes with its own ReflectionSupport and AnnotationSupport classes that might be useful and save you from pulling in yet another library.
In case you use Spring Test try org.springframework.test.util.ReflectionTestUtils
ReflectionTestUtils.setField(testObject, "person", mockedPerson);
Pretty late to the party, but I was struck here and got help from a friend. The thing was not to use PowerMock. This works with the latest version of Mockito.
Mockito comes with this org.mockito.internal.util.reflection.FieldSetter.
What it basically does is helps you modify private fields using reflection.
This is how you use it:
#Mock
private Person mockedPerson;
private Test underTest;
// ...
#Test
public void testMethod() {
FieldSetter.setField(underTest, underTest.getClass().getDeclaredField("person"), mockedPerson);
// ...
verify(mockedPerson).someMethod();
}
This way you can pass a mock object and then verify it later.
Here is the reference.
I already found the solution to this problem which I forgot to post here.
#RunWith(PowerMockRunner.class)
#PrepareForTest({ Test.class })
public class SampleTest {
#Mock
Person person;
#Test
public void testPrintName() throws Exception {
PowerMockito.whenNew(Person.class).withNoArguments().thenReturn(person);
Test test= new Test();
test.testMethod();
}
}
Key points to this solution are:
Running my test cases with PowerMockRunner: #RunWith(PowerMockRunner.class)
Instruct Powermock to prepare Test.class for manipulation of private fields: #PrepareForTest({ Test.class })
And finally mock the constructor for Person class:
PowerMockito.mockStatic(Person.class);
PowerMockito.whenNew(Person.class).withNoArguments().thenReturn(person);
Following code can be used to initialize mapper in REST client mock. The mapper field is private and needs to be set during unit test setup.
import org.mockito.internal.util.reflection.FieldSetter;
new FieldSetter(client, Client.class.getDeclaredField("mapper")).set(new Mapper());
if u are using spring boot test and cant find neither of WhiteBox, FeildSetter; u can simply use org.springframework.test.util.ReflectionTestUtils
this is an example:
import org.springframework.test.util.ReflectionTestUtils;
//...
#Mock
private Person mockedPerson;
private Test underTest;
// ...
#Test
public void testMethod() {
ReflectionTestUtils.setField(underTestObject, "person", mockedPerson);
// ...
}
Using #Jarda's guide you can define this if you need to set the variable the same value for all tests:
#Before
public void setClientMapper() throws NoSuchFieldException, SecurityException{
FieldSetter.setField(client, client.getClass().getDeclaredField("mapper"), new Mapper());
}
But beware that setting private values to be different should be handled with care. If they are private are for some reason.
Example, I use it, for example, to change the wait time of a sleep in the unit tests. In real examples I want to sleep for 10 seconds but in unit-test I'm satisfied if it's immediate. In integration tests you should test the real value.
The best way until now, I think that is
org.springframework.test.util.ReflectionTestUtils
Im about to mock the private String mockField in FooService.class inside FooServiceTest.java
FooService.java:
#Value("${url.image.latest}")
private String latestImageUrl;
FooServiceTest.java:
#InjectMocks
FooService service;
#BeforeEach
void setUp() {
ReflectionTestUtils.setField(service, // inject into this object
"latestImageUrl", // assign to this field
"your value here"); // object to be injected
}
commons-lang3
import org.apache.commons.lang3.reflect.FieldUtils;
FieldUtils.writeField(object, fieldName, value, true);

How to mock feign.Client.Default with Mockito

I'm writing a Dropwizard application and using Feign for building client calls to outside services. I have custom encoders and decoders I'm registering with the feign.Builder like so:
this.feignBuilder = Feign.builder()
.contract(new JAXRSContract()) // we want JAX-RS annotations
.encoder(new JacksonEncoder()) // same as what dropwizard is using
.decoder(new CustomDecoder())
.errorDecoder(new CustomErrorDecoder())
.requestInterceptor(new AuthKeyInterceptor(config.getInterceptor()));
I'm writing unit tests for the feign client calls so I can watch how the feign machinery deals with my encoder/decoder overrides and bubbles on exceptions. I'm not interested in writing integration tests with a fake server right now (this is the most common type of test i see people writing for this situation).
This should be straight forward. I want to mock the point at which feign makes the request and have it return my fake response. That means I should mock the call to feign.Client.Default.execute so it returns my fake response when it makes the request a this call site. An example of what that mock looks like:
String responseMessage = "{\"error\":\"bad\",\"desc\":\"blah\"}";
feign.Response feignResponse = FeignFakeResponseHelper.createFakeResponse(404,"Bad Request",responseMessage);
Client.Default mockFeignClient = mock(Client.Default.class);
try {
when(mockFeignClient.execute(any(feign.Request.class),any(Request.Options.class))).thenReturn(feignResponse);
} catch (IOException e) {
assertThat(true).isFalse(); // fail nicely
}
No luck. The Cleint.Default class isn't mocked when I reach the call site for the request in the code. What am I doing wrong?
As mentioned before, Mockito is not powerful enough.
I solved this with a manual mock.
It's easier than it sounds:
MyService.Java
public class MyService{
//My service stuff
private MyFeignClient myFeignClient;
#Inject //this will work only with constructor injection
public MyService(MyFeignClient myFeignClient){
this.MyFeignClient = myFeignClient
}
public void myMethod(){
myFeignClient.remoteMethod(); // We want to mock this method
}
}
MyFeignClient.Java
#FeignClient("target-service")
public interface MyFeignClient{
#RequestMapping(value = "/test" method = RequestMethod.GET)
public void remotemethod();
}
If you want to test the code above while mocking the feignclient, do this:
MyFeignClientMock.java
#Component
public class MyFeignClientMock implements MyFeignClient {
public void remoteMethod(){
System.out.println("Mocked remoteMethod() succesfuly");
}
}
MyServiceTest.java
#RunWith(SpringJUnit4ClassRunner.class)
public class MyServiceTest {
private MyService myService;
#Inject
private MyFeignClientMock myFeignClientMock;
#Before
public void setUp(){
this.myService = new MyService(myFeignClientMock); //inject the mock
}
//Do tests normally here...
}
It turns out Mockito is not powerful enough to do the thing I assumed it could do. The correct solution is to use PowerMockito to mock the constructor so Client.Default returns the mocked instance when it is instantiated in the class that holds that reference.
After a lot of compilation-error pain I got PowerMockito to compile and it seemed like it was going to work. Alas it failed to return my mock and the calls were still going through. I've tried PowerMockito in the past and never got around to using it because of the extra problems it caused. So I'm still of the opinion that it's not super easy to just plug and play.
It's a shame that trying to do something like this is so hard.

External Mocked method returns Null in the Actual Class

When I am testing the Mocked external call, I am not seeing the mocked value of report instead it is Null and my testing is failing. I can see the Mocked value (of report) in the Test Class but not in BusinessServiceImpl class and Application(Method Return) is not modified as I expected.
My Expectation: When I mock the External call in Impl class, mocked value should be available there and rest everything else happen as if real method was called to complete the Unit Testing.
Implementation code:
package com.core.business.service.dp.fulfillment;
import com.core.business.service.dp.payment.PaymentBusinessService;
public class BusinessServiceImpl implements BusinessService { // Actual Impl Class
private PaymentBusinessService paymentBusinessService = PluginSystem.INSTANCE.getPluginInjector().getInstance(PaymentBusinessService.class);
#Transactional( rollbackOn = Throwable.class)
public Application applicationValidation (final Deal deal) throws BasePersistenceException {
Application application = (Application) ApplicationDTOFactory.eINSTANCE.createApplication();
//External Call we want to Mock
String report = paymentBusinessService.checkForCreditCardReport(deal.getId());
if (report != null) {
application.settingSomething(true); //report is Null and hence not reaching here
}
return application;
}
}
The test code:
#Test(enabled = true)// Test Class
public void testReCalculatePrepaids() throws Exception {
PaymentBusinessService paymentBusinessService = mock(PaymentBusinessService.class);
//Mocking External Call
when(paymentBusinessService.checkForCreditCardReport(this.deal.getId())).thenReturn(new String ("Decline by only Me"));
String report = paymentBusinessService.checkForCreditCardReport(this.deal.getId());
// Mocked value of report available here
//Calling Impl Class whose one external call is mocked
//Application is not modified as expected since report is Null in Impl class
Application sc = BusinessService.applicationValidation(this.deal);
}
The main purpose of Mockito is to isolate the tests. As in, when you are testing your BusinessServiceImpl you should mock all its dependencies.
This is exactly what you are trying to do with your example above. Now for the mocking to work, the mocked object has to be injected into the class you are trying to test, in this case the BusinessServiceImpl.
One way of doing this is by passing the dependecy by the contructor of the class, dependency injection. Or you could look at how it can be done with Spring and ReflectionTestUtils.
I got it done and I am successfully able to get the Mocked value without touching the BusinessServiceImpl class at all. Steps I followed are:
1. #Mock PaymentBusinessService paymentBusinessService = mock(PaymentBusinessService.class);
2. #InjectMocks private PaymentBusinessService paymentBusinessService = PluginSystem.INSTANCE.getPluginInjector().getInstance(PaymentBusinessService.class);
And then simply ran the above test and I could see the value of report as "Decline by only Me" in the BusinessServiceImpl and my test case passed

Categories