I have this code in my service:
public String requestValue() {
Call call = okHttpClient.newCall(new Request.Builder().url("external-url").build());
Response response = call.execute();
return response.body().string();
}
How can I mock the result of this call in a Junit test?
public void testRequestValue() {
// TODO mock http response
String result = myService.requestValue();
assertEquals("value", result);
}
note: naive solution with Mockito does not work. Mockito.eq does not trigger on Request objects (seems like Request.equals provides incorrect result for identical requests).
Request request = new Request.Builder().url("external-url").build();
Response response = new Response.Builder()
.request(request)
.protocol(Protocol.HTTP_2)
.code(200)
.message("")
.body(ResponseBody.create("value", MediaType.get("application/json")))
.build();
Call call = Mockito.mock(Call.class);
Mockito.when(call.execute()).thenReturn(response);
Mockito.when(okHttpClientMock.newCall(Mockito.eq(request))).thenReturn(call);
You could use wiremock or the MockServer provided by okhttp
Related
I am really bugged with an unmarshalling issue with the response from the SOAP service. I am using springboot application and WebServiceTemplate for calling an existing SOAP service. I am using below code to set up beans for marshalling and webservicetemplate. Any help is highly appreciated.
On calling webServiceTemplate.marshalSendAndReceive(request); I am expecting TravelResponse object but it is giving me JAXBElement<TravelResponse> object as response. I need help to understand
1) why is it giving above response instead of TravelResponse
2) How to convert to TravelResponse
Code snippet below:
#Bean
Jaxb2Marshaller jaxb2Marshaller() {
Jaxb2Marshaller jaxb2Marshaller = new Jaxb2Marshaller();
jaxb2Marshaller.setContextPath("com.cater.trip.simple_api.trip.v1");
return jaxb2Marshaller;
}
#Bean
public WebServiceTemplate webServiceTemplate() throws Exception {
WebServiceTemplate webServiceTemplate = new WebServiceTemplate();
webServiceTemplate.setMessageFactory(getMessageFactory());
webServiceTemplate.setMarshaller(jaxb2Marshaller());
webServiceTemplate.setUnmarshaller(jaxb2Marshaller());
webServiceTemplate.setDefaultUri(defaultUri);
webServiceTemplate.setMessageSender(getMessageSender());
return webServiceTemplate;
}
#Bean
public SaajSoapMessageFactory getMessageFactory() {
return new SaajSoapMessageFactory();
}
#Bean
public HttpComponentsMessageSender getMessageSender() {
return new HttpComponentsMessageSender();
}
#Override
public Object getData( ) {
ObjectFactory clientFac = new ObjectFactory();
TravelRequest request = populateRequest(clientFac);
TravelResponse res = (TravelResponse) webServiceTemplate.marshalSendAndReceive(request);
return res;
}
As per Spring's doc, WebServiceTemplate.marshalSendAndReceive(Object requestPayload)
Sends a web service message that contains the given payload, marshalled by the configured Marshaller. Returns the unmarshalled payload of the response message, if any.
This will only work with a default uri specified!
So, you can do this to return the expected response.
JAXBElement<TravelResponse> res = (JAXBElement<TravelResponse>) webServiceTemplate.marshalSendAndReceive(request);
return res.getValue();
Try JaxbIntrospector.getValue to get the actual response from JAXB element.
TravelResponse response = JaxbIntrospector.getValue(jaxbElement);
I have a resource method which produces a streaming download:
#GET
#Path("/{assetId}")
#Produces(MediaType.APPLICATION_OCTET_STREAM)
public Response download(#PathParam("assetId") String assetId) {
StreamingOutput stream = os -> service.download(assetId, os);
return Response.ok(stream).build();
}
I want to unit test this with a mock service object. I already have:
private static AssetsService service = Mockito.mock(AssetsService.class);
#ClassRule
public final static ResourceTestRule resource = ResourceTestRule.builder()
.addResource(new AssetsResource(service))
.addProvider(MultiPartFeature.class)
.build();
#Test
public void testDownload() {
reset(service);
// how to get an output stream from this?
resource.client().target("/assets/123").request().get();
}
Per my comment in the test, what do I need to do in order to get an outputstream from the response? I find the jersey client API pretty confusing.
Once I have this, I'll stub the service call so that it writes a known file, and test that it's received correctly.
Try this:
Response response = resource.client().target("/assets/123").request().get();
InputStream is = response.readEntity(InputStream.class);
Please ignore the spelling mistake, I cannot copy code so I have typed the whole thing and changed name of controller and method.
WEB API 2
Controller:
// Controller name is Test
public HttpResponseMessage Method1(int param1) // Post method
{
// return string
}
If I create an object of controller in test case then it is working fine. But if I want to test in localhost using following code:
Unit Test:
public void Method1Test()
{
HttpResponseMessage response;
HttpConfiguration config = new HttpConfiguration();
config.Routes.MapHttpRoute("DefaultApi", "api/{controller}/{id}");
HttpServer server = new HttpServer(config);
using(var client = new HttpClient(server))
{
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, "http://localhost:5022/api/test?param1=1");
request.Content = new ObjectContent<int>(param1, new JsonMediaTypeFormatter());
response = client.SendAsync(request, CancellationToken.None).Result;
};
Assert.AreEqual(HttpStatusCode.OK, response.StatusCode);
}
Now, my test case is failing. I used the same code in different project and it worked. May be it is the way I am trying to call Post method. Is this the right way to call post method with Int parameter in URL?
In help page, under API column it shows:
POST api/test/param1={param1}
Also I have put some stop point in actual service I am cursor is not stopping at that point. Why?
If I want to call the same service from browser, what URL should I pass? Is it -
http://localhost:5022/api/test?param1=1
Or something else?
I figured it out. Following is the correct unit test method but this has some extra information which I have not provided earlier i.e., passing object as an input for the service.
private void Method1Test(ObjectClass obj)
{
HttpResponseMessage response = null;
HttpConfiguration config = new HttpConfiguration();
config.Routes.MapHttpRoute("DefaultApi", "api/{controller}/{id}");
HttpServer server = new HttpServer(config);
using (var client = new HttpClient(server))
{
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, "http://localhost:5022/api/test/1");
request.Content = new ObjectContent<ObjectClass>(obj, new JsonMediaTypeFormatter());
response = client.SendAsync(request, CancellationToken.None).Result;
};
Assert.AreEqual(HttpStatusCode.OK, response.StatusCode);
}
So the correct URL that I was looking for was
http://localhost:5022/api/test/1
Sorry, It took long to post this answer. This method is working like a charm for more then 2 years.
I have a trigger that fires when an opportunity is updated, as part of that I need to call our API with some detail from the opportunity.
As per many suggestions on the web I've created a class that contains a #future method to make the callout.
I'm trying to catch an exception that gets thrown in the #future method, but the test method isn't seeing it.
The class under test looks like this:
public with sharing class WDAPIInterface {
public WDAPIInterface() {
}
#future(callout=true) public static void send(String endpoint, String method, String body) {
HttpRequest req = new HttpRequest();
req.setEndpoint(endpoint);
req.setMethod(method);
req.setBody(body);
Http http = new Http();
HttpResponse response = http.send(req);
if(response.getStatusCode() != 201) {
System.debug('Unexpected response from web service, expecte response status status 201 but got ' + response.getStatusCode());
throw new WDAPIException('Unexpected response from web service, expecte response status status 201 but got ' + response.getStatusCode());
}
}
}
here's the unit test:
#isTest static void test_exception_is_thrown_on_unexpected_response() {
try {
WDHttpCalloutMock mockResponse = new WDHttpCalloutMock(500, 'Complete', '', null);
WDAPIInterface.send('https://example.com', 'POST', '{}');
} catch (WDAPIException ex) {
return;
}
System.assert(false, 'Expected WDAPIException to be thrown, but it wasnt');
}
Now, I've read that the way to test #future methods is to surround the call with Test.startTest() & Test.endTest(), however when I do that I get another error:
METHOD RESULT
test_exception_is_thrown_on_unexpected_response : Skip
MESSAGE
Methods defined as TestMethod do not support Web service callouts, test skipped
So the question is, how do I unit test a #future method that makes an callout?
The callout is getting skipped because the HttpCalloutMock isn't being used.
I assume that WDHttpCalloutMock implements HttpCalloutMock?
If so, a call to Test.setMock should have it return the mocked response to the callout.
WDHttpCalloutMock mockResponse = new WDHttpCalloutMock(500, 'Complete', '', null);
Test.setMock(HttpCalloutMock.class, mockResponse);
WDAPIInterface.send('https://example.com', 'POST', '{}');
Incidentally, the Salesforce StackExchange site is a great place to ask Salesforce specific questions.
I wrote a Rest-Service which i would like to test.
I wanna run a JUnit test without having my server run. For this I am using the Server-side Mock Framework of RestEasy.
My question is, how can I make a Http-Put or Http-Post request with this framework with an marshalled Java Object in the Http-Body???
The Code below runs fine for an Http-Get, but how to make a Put or Post, maybe someone got some example code for this???
#Test
public void testClient() throws Exception {
Dispatcher dispatcher = MockDispatcherFactory.createDispatcher();
POJOResourceFactory noDefaults = new POJOResourceFactory(
MyClass.class);
dispatcher.getRegistry().addResourceFactory(noDefaults);
{
MockHttpRequest request = MockHttpRequest.get("/message/test/"
+ requestParam);
MockHttpResponse response = new MockHttpResponse();
dispatcher.invoke(request, response);
assertEquals(HttpServletResponse.SC_OK, response.getStatus());
}
}
A bit late response but , might have some use for someone.
This is how i usually test my PUT requests. Hope it helps
#Test
public void testPUT() throws Exception {
POJOResourceFactory noDefaults = new POJOResourceFactory(REST.class);
Dispatcher dispatcher = MockDispatcherFactory.createDispatcher();
dispatcher.getRegistry().addResourceFactory(noDefaults);
String url = "your_url_here";
MockHttpRequest request = MockHttpRequest.put(url);
request.accept(MediaType.APPLICATION_JSON);
request.contentType(MediaType.APPLICATION_JSON_TYPE);
// res being your resource object
request.content(res.toJSONString().getBytes());
MockHttpResponse response = new MockHttpResponse();
dispatcher.invoke(request, response);
Assert.assertEquals( HttpStatus.SC_CREATED,response.getStatus());
}