I want to create a Stub for an API and want to verify API call and response returned by the server. for that i have implemented WireMock example :
import org.junit.Rule;
import org.junit.Test;
import com.github.tomakehurst.wiremock.junit.WireMockRule;
public class MockTestDemo {
private static final int WIREMOCK_PORT = 8080;
#Rule
public WireMockRule wireMockRule = new WireMockRule(WIREMOCK_PORT);
#Test
public void exampleTest() {
stubFor(get(urlEqualTo("/login")).withHeader("Accept", equalTo("application/json"))
.willReturn(aResponse().withStatus(200).withBody("Login Success")
.withStatusMessage("Everything was just fine!"))
.willReturn(okJson("{ \"message\": \"Hello\" }")));
verify(getRequestedFor(urlPathEqualTo("http://localhost:8080/login"))
.withHeader("Content-Type",equalTo("application/json"))); }
}
But getting below error :
com.github.tomakehurst.wiremock.client.VerificationException: Expected at least one request matching: {
"urlPath" : "localhosturl/login",
"method" : "GET",
"headers" : {
"Content-Type" : {
"equalTo" : "application/json"
}
}
}
Requests received: [ ]
at com.github.tomakehurst.wiremock.client.WireMock.verificationExceptionForNearMisses(WireMock.java:545)
at com.github.tomakehurst.wiremock.client.WireMock.verifyThat(WireMock.java:532)
at com.github.tomakehurst.wiremock.client.WireMock.verifyThat(WireMock.java:511)
at com.github.tomakehurst.wiremock.client.WireMock.verify(WireMock.java:549)
at com.wiremock.test.MockTestDemo.exampleTest(MockTestDemo.java:23)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at com.github.tomakehurst.wiremock.junit.WireMockRule$1.evaluate(WireMockRule.java:73)
at org.junit.rules.RunRules.evaluate(RunRules.java:20)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:538)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:760)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:460)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:206)
If I comment verify part then test executed successfully also i have verified the same using postman by calling http://localhost:8080/login and it returning response successfully ?
Is any thing I'm missing here ?
In your code you are stubbing out a response and then verifying that a request has been made for that stub. You are not however making a call to the endpoint and so the test is failing.
You need to invoke the endpoint before verifying that it is called.
If you use Apache Commons HttpClient, you could write your test as:
#Test
public void exampleTest() throws Exception {
stubFor(get(urlEqualTo("/login")).withHeader("Accept", equalTo("application/json"))
.willReturn(aResponse().withStatus(200).withBody("Login Success")
.withStatusMessage("Everything was just fine!"))
.willReturn(okJson("{ \"message\": \"Hello\" }")));
String url = "http://localhost:8080/login";
HttpClient client = HttpClientBuilder.create().build();
HttpGet request = new HttpGet(url);
request.addHeader("Content-Type", "application/json");
request.addHeader("Accept", "application/json");
HttpResponse response = client.execute(request);
verify(getRequestedFor(urlPathEqualTo("/login"))
.withHeader("Content-Type", equalTo("application/json")));
}
Kindly, recommend using a class rule annotation/field (#ClassRule) for JUnit 4 (in those cases, where config could be reused on multiple unit tests).
#Rule could cause unexpected behaviors on async or http requests contexts, when stubs aren't registered yet.
Versions: 2.21.0 -> ... -> 2.31.0.
Note: In my particular case, had multiple tests reusing config and all the requests where executed correctly (debugging & checking mocked responses deserialized onto in-memory DTOs).
Then:
// ... WIREMOCK_PORT
#ClassRule
public static final WireMockClassRule WIRE_MOCK_RULE = new WireMockClassRule(WIREMOCK_PORT); // public
Also, recommend verifying mocked request was made to WireMock registered stubs.
Steps:
Create stub: WIRE_MOCK_RULE.stubFor(get(urlPathMatching(...))) // get, post, ...
Hit mocked endpoint with a Http client
Verify stub was invoked: verify(getRequestedFor(urlPathMatching(...)))
//{get, post, ...}RequestedFor(...) API methods for a particular HTTP request
verify(getRequestedFor(urlPathMatching("a-url-pattern"))); //urlEqualTo, ...
Related
I am currently trying to create expectations and get them verified by mockServer (can be found here).
I've read their documentation several times now but I can't find out why the verifcation of my expectation fails.
This is my code
#Rule
public MockServerRule mockServerRule = new MockServerRule(this, 9000);
private MockServerClient mockServer;
#Test
public void testVerification() {
mockServer.when(
HttpRequest.request()
.withMethod("POST")
.withPath("/validate")
.withHeader("\"Content-type\", \"application/json\"")
.withBody("{username: 'foo', password: 'bar'}"))
.respond(
HttpResponse.response()
.withStatusCode(401)
.withHeaders(
new Header("Content-Type", "application/json; charset=utf-8"),
new Header("Cache-Control", "public, max-age=86400"))
.withBody("{ message: 'incorrect username and password combination' }")
.withDelay(TimeUnit.SECONDS,1)
);
mockServer.verify(HttpRequest.request().withMethod("POST")
.withPath("/validate")
.withBody("{username: 'foo', password: 'bar'}"),
VerificationTimes.exactly(1));
}
When trying to verify, I always get the error
java.lang.AssertionError: Request not found exactly once, expected:<{
"method" : "POST",
"path" : "/validate",
"body" : "{username: 'foo', password: 'bar'}"}> but was:<>
at org.mockserver.client.server.MockServerClient.verify(MockServerClient.java:267)
at it.HttpTest.testVerification(HttpTest.java:61)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.mockserver.junit.MockServerRule$1.evaluate(MockServerRule.java:107)
at org.junit.rules.RunRules.evaluate(RunRules.java:20)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:89)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:41)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:542)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:770)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:464)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:210)
Well, you forgot to send a request to your mock server. You only mocked its behaviour and then you check if the server has been called, but you missed the call.
Try it with something like this:
public int callValidateUrl() throws IOException {
URL url = new URL("http://localhost:9000/validate");
HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.setRequestMethod("POST");
con.setRequestProperty("Content-Type", "application/json");
con.setDoOutput(true);
String jsonInputString = "{username: 'foo', password: 'bar'}";
try (OutputStream os = con.getOutputStream()) {
byte[] input = jsonInputString.getBytes("utf-8");
os.write(input, 0, input.length);
}
return con.getResponseCode();
}
If you are using Spring, RestTemplate is easier to use.
HI i am trying to develop test cases with JUNIT + MOCKITO and facing an issue due to this ..
This is the method which i am trying to test
public Response create(Request request)
throws SQLException, InvalidSecretKeyException, UnsupportedEncodingException, GeneralSecurityException,
InvalidParametersException, InvalidAuthKeyException, ConstraintViolationExceptions, InvalidKeyHashException, InvalidApplicationKeyException {
User user = userService.validateAndReturnUserBy(request.headers("AuthKey"));
ApplicationWrapper applicationWrapper = JsonUtil.deSerialize(request.body(), ApplicationWrapper.class);
//System.out.println(applicationWrapper.getSecretKey());
Application application=new Application();
application.setKey(getApplicationKey(user.getUserName(), applicationWrapper.getType().getName(), applicationWrapper.getName()));
System.out.println("GEN KEY ::::" + getApplicationKey(user.getUserName(), applicationWrapper.getType().getName(), applicationWrapper.getName()));
application.setName(applicationWrapper.getName());
application.setPackageName(applicationWrapper.getPackageName());
application.setSendOTPInResponse(applicationWrapper.getSendOTPInResponse());
application.setType(applicationWrapper.getType());
application.setSignature(applicationWrapper.getSignature());
application.setCreatedAt(getMysqlTimeStamp());
application.setCreatedBy(user);
application.setUpdatedBy(user.getId());
application.setOtpExpiry(applicationWrapper.getOtpExpiry());
application.setOtpLength(applicationWrapper.getOtpLength());
application.setRandomNumber(tempRandomNumber);
validator.validate(application);
applicationRepository.create(application);
System.out.println(applicationWrapper);
Application thisApp =applicationRepository.getBy(application);
List<String> secretKeys = applicationWrapper.getSecretKey();
System.out.println("Application Service ::: \n"+thisApp);
insertApplicationSecretKeys(secretKeys,thisApp);
Map<String, String> responseBody = new HashMap<>();
responseBody.put("application_key", application.getKey());
responseBody.put("message", "Application created Successfully");
return new Response("success", responseBody);
}
And this is my Mockito + JUnit Test case
#Test
public void shouldCreate() throws SQLException, ResourceNotFoundException, InvalidSecretKeyException,
UnsupportedEncodingException, GeneralSecurityException, InvalidAuthKeyException, InvalidParametersException, ConstraintViolationExceptions, InvalidKeyHashException, SendGridException, InvalidApplicationKeyException {
when(request.headers("AuthKey")).thenReturn("some-auth-key");
when(userService.validateAndReturnUserBy("some-auth-key")).thenReturn(user);
when(request.body()).thenReturn(JsonUtil.toJson(make(a(ApplicationWrapperMaker.ApplicationWrapper))));
when(applicationTypeRepository.getByName("WEB")).thenReturn(make(a(ApplicationTypeMaker.ApplicationType)));
when(userRepository.getByAuthKey("some-auth-key")).thenReturn(user);
//doNothing().when(appService).insertApplicationSecretKeys(make(a(ApplicationSecretKeyMaker.ApplicationSecretKey)), make(a(Application)));
//doThrow(new RuntimeException("App created")).when(appService).insertApplicationSecretKeys(make(a(ApplicationSecretKeyMaker.ApplicationSecretKey)), make(a(Application)));
Response response = applicationService.create(request);
assertEquals("success", response.getStatus());
assertNotNull(response.getBody());
}
There is an issue where insertApplicationSecretKeys(secretKeys,thisApp);
Is being called .. As the Created application object is just a mock object this method is returning null and NullPointer exception is coming at this line.
this app variable is coming NULL.
Please help.
EDIT : HERE IS THE STACKTRACE AND OUTPUT
java.lang.NullPointerException
at com.sendotp.service.ApplicationService.insertApplicationSecretKeys(ApplicationService.java:297)
at com.sendotp.service.ApplicationService.create(ApplicationService.java:92)
at com.sendotp.service.ApplicationServiceTest.shouldCreate(ApplicationServiceTest.java:162)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.junit.rules.ExpectedException$ExpectedExceptionStatement.evaluate(ExpectedException.java:239)
at org.junit.rules.RunRules.evaluate(RunRules.java:20)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.mockito.internal.runners.JUnit45AndHigherRunnerImpl.run(JUnit45AndHigherRunnerImpl.java:37)
at org.mockito.runners.MockitoJUnitRunner.run(MockitoJUnitRunner.java:62)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:68)
Output ::
GEN KEY ::::AhLDuwI4x34cP6-pr3WJSKoHZ7ltat13CdAcWlkZ8DHyiIk9b8-606JJ9ZPPPbTRWdnU7bPQYp4jphpdfqFoOwHs0uEc0ewE2-MHe8Yyu0XxZZQ7nw7itYVTXNFPp-a2NFP8AZ89QIznIzGstVWyO7eL7DS_qmam8BUF5XHN-VA=
ApplicationWrapper{name='someApplicationName', type=com.sendotp.model.ApplicationType#57f791c6, packageName='some.package.name', otpExpiry=86400, senderId='somesenderId', otpLength=6, requestPerIp=100, key='null', createdBy=null, updatedBy=0, createdAt=null, updatedAt=null, randomNumber='null', secretKey=[121212, 32234324], signature='some-signature,#OTP', sendOTPInResponse=0}
Application Service :::
null
Your method create is doing too much.
Especially instantiating the Application object schould be done outside the method. Object creation of other classes providing business logic should not be doen within the class using this dependency. Dependency inversion should be applied.
The simplest way is to pass the Application object as parameter to the method (which shold be renamed to configure then). In that case you could replace it by a mock on which you could verify the expected method calls.
I am getting the below exception trying to make a get request using a Jersey Client. If I post requestPath into my browser, I get the expected Json response.
Result when I visit requestPath from my browser:
{ "application":[
], "error":0 }
Client client = Client.create();
client.addFilter(new ClientFilter() {
#Override
public ClientResponse handle(ClientRequest request) throws ClientHandlerException {
request.getHeaders().putSingle(HttpHeaders.CONTENT_TYPE, "application/json");
return getNext().handle(request);
}
});
WebResource webResource = client.resource(requestPath)
ClientResponse response = webResource
.accept("application/json")
.get(ClientResponse.class);
String responseStr = response.getEntity(String.class);
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-client</artifactId>
<version>1.18.1</version>
</dependency>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-json</artifactId>
<version>1.18.1</version>
</dependency>
java.lang.IllegalArgumentException: Error parsing media type 'application/json; charset=UTF-8"'
at com.sun.jersey.core.impl.provider.header.MediaTypeProvider.fromString(MediaTypeProvider.java:79)
at com.sun.jersey.core.impl.provider.header.MediaTypeProvider.fromString(MediaTypeProvider.java:53)
at javax.ws.rs.core.MediaType.valueOf(MediaType.java:119)
at com.sun.jersey.api.client.ClientResponse.getType(ClientResponse.java:695)
at com.sun.jersey.api.client.ClientResponse.getEntity(ClientResponse.java:612)
at com.sun.jersey.api.client.ClientResponse.getEntity(ClientResponse.java:586)
at MyTest.test(MyTest.java:31)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:117)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:42)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:262)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:84)
Caused by: java.text.ParseException: Unbalanced quoted string
at com.sun.jersey.core.header.reader.HttpHeaderReaderImpl.processQuotedString(HttpHeaderReaderImpl.java:313)
at com.sun.jersey.core.header.reader.HttpHeaderReaderImpl.process(HttpHeaderReaderImpl.java:243)
at com.sun.jersey.core.header.reader.HttpHeaderReaderImpl.next(HttpHeaderReaderImpl.java:184)
at com.sun.jersey.core.header.reader.HttpHeaderReader.nextSeparator(HttpHeaderReader.java:112)
at com.sun.jersey.core.header.reader.HttpHeaderReader.readParameters(HttpHeaderReader.java:239)
at com.sun.jersey.core.impl.provider.header.MediaTypeProvider.valueOf(MediaTypeProvider.java:97)
at com.sun.jersey.core.impl.provider.header.MediaTypeProvider.fromString(MediaTypeProvider.java:77)
... 28 more
The Content-Type header, which server returns, is broken:
java.lang.IllegalArgumentException: Error parsing media type 'application/json; charset=UTF-8"'
...
Caused by: java.text.ParseException: Unbalanced quoted string
(note dangling ")
you can workaround this like described here: How to override response header in jersey client
UPDATE
I've setup a small test as follows:
Launched a small "fake" HTTP server on the command line, which returns the broken "Content-Type" header
while true
do
cat<<EOF | nc -l 8080
HTTP/1.1 200 OK
Content-Type: application/json; charset=UTF-8"
Hello
EOF
done
Tried to access it with Jersey Client, as follows:
Client client = Client.create();
WebResource resource = client.resource("http://localhost:8080");
String response = resource.accept("application/json").get(String.class);
System.out.println(response);
That resulted in an Exception, looking pretty much one you have:
Exception in thread "main" java.lang.IllegalArgumentException: Error parsing media type 'application/json; charset=UTF-8"\r\n'
at com.sun.jersey.core.impl.provider.header.MediaTypeProvider.fromString(MediaTypeProvider.java:79)
at com.sun.jersey.core.impl.provider.header.MediaTypeProvider.fromString(MediaTypeProvider.java:53)
at javax.ws.rs.core.MediaType.valueOf(MediaType.java:119)
...
Caused by: java.text.ParseException: Unbalanced quoted string
at com.sun.jersey.core.header.reader.HttpHeaderReaderImpl.processQuotedString(HttpHeaderReaderImpl.java:263)
at com.sun.jersey.core.header.reader.HttpHeaderReaderImpl.process(HttpHeaderReaderImpl.java:192)
...
Now, I've added a filter to override the response "Content-Type":
client.addFilter(new ClientFilter() {
#Override
public ClientResponse handle(ClientRequest request) throws ClientHandlerException {
ClientResponse response = getNext().handle(request);
response.getHeaders().put(HttpHeaders.CONTENT_TYPE, Arrays.asList(MediaType.APPLICATION_JSON));
return response;
}
});
and then re-run the test and voila:
Hello
I'm calling a REST service using this test code:
public class TestRESTServices {
private static final String BASE_URL = "http://localhost/ma.ge.persistence-1.0/rest/reference";
private static URI uri = UriBuilder.fromUri(BASE_URL).port(8080).build();
private static Client client = ClientBuilder.newClient();
#Test
public void createAndDeleteAReference() {
Reference r = ReferenceFactory.createReference("Maz",
"dummy", 1.7);
Response response = client.target(uri).request().post(Entity.entity(r, MediaType.APPLICATION_JSON));
assertEquals(Response.Status.CREATED, response.getStatusInfo());
URI referenceURI = response.getLocation();
// Get the posted reference
response = client.target(referenceURI).request().get();
Reference retreivedRef = response.readEntity(Reference.class);
assertEquals(Response.Status.OK, response.getStatusInfo());
assertEquals(retreivedRef.getName(), r.getName());
}
But I get the following error:
javax.ws.rs.ProcessingException: Unable to invoke request
at org.jboss.resteasy.client.jaxrs.engines.ApacheHttpClient4Engine.invoke(ApacheHttpClient4Engine.java:287)
at org.jboss.resteasy.client.jaxrs.internal.ClientInvocation.invoke(ClientInvocation.java:407)
at org.jboss.resteasy.client.jaxrs.internal.ClientInvocationBuilder.get(ClientInvocationBuilder.java:159)
at ma.gesto.persistence.TestRESTServices.createAndDeleteAReference(TestRESTServices.java:34)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
Caused by: java.lang.IllegalStateException: Invalid use of BasicClientConnManager: connection still allocated.
Make sure to release the connection before allocating another one.
at org.apache.http.impl.conn.BasicClientConnectionManager.getConnection(BasicClientConnectionManager.java:162)
at org.apache.http.impl.conn.BasicClientConnectionManager$1.getConnection(BasicClientConnectionManager.java:139)
at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:456)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:906)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:805)
at org.jboss.resteasy.client.jaxrs.engines.ApacheHttpClient4Engine.invoke(ApacheHttpClient4Engine.java:283)
... 26 more
The Client interface represents external resources. As such, it is a critical mistake to create and store one in a static variable. This is wrong:
private static Client client = ClientBuilder.newClient();
This is ok for unit testing:
private Client client;
#Before
public void setUp() {
this.client = ClientBuilder.newClient();
}
#After
public void tearDown() {
this.client.close();
}
In normal code you would want to wrap Client usage in a try-with-resources or try..finally:
Client client = ClientBuilder.newClient();
try {
// use the client to make requests
} finally {
client.close();
}
Ideally there would be a way to manage a pool of Client instances for reuse.
You also need to close your Response to free up the connection.
See explanations here:
Resteasy Client keeping connection allocated after a method throws an Exception
I'm testing an api endpoint which works from a http poster (namely PAW) but I cant get a test in the code to pass.
I'm new to both Mockito and MockMVC so any help would be appreciated.
Test below:
#Test
public void createPaymentTest() throws Exception {
User user = new User("ben", "password", "a#a.com");
SuccessResponseDTO successDTO = new SuccessResponseDTO();
successDTO.setSuccess(true);
when(userService.getLoggedInUser()).thenReturn(user);
when(paymentService.makePayment(Mockito.any(PaymentRequestDTO.class), Mockito.any(User.class))).thenReturn(successDTO.getSuccess());
this.mockMvc.perform(post("/payment")).andExpect(status().isOk())
.andExpect(content().contentType(MediaType.APPLICATION_JSON)).andDo(MockMvcResultHandlers.print())
.andExpect(jsonPath("$.success").value(successDTO.getSuccess()));
}
SuccessResponseDTO just contains one attribute, a boolean 'success'.
The method it's testing is below:
#RequestMapping(value = "/payment", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
#ResponseBody
public SuccessResponseDTO createPayment(#RequestBody PaymentRequestDTO payment) {
User loggedInUser = userService.getLoggedInUser();
LOGGER.info("Logged in user found...creating payment...");
Assert.notNull(payment.getAccountId(), "Missing user account id");
Assert.notNull(payment.getPayeeAccountNumber(), "Missing payee acount number");
Assert.notNull(payment.getPayeeName(), "Missing payee name");
Assert.notNull(payment.getPayeeSortCode(), "Missing payee sort code");
Assert.notNull(payment.getPaymentAmount(), "Missing payee amount");
Assert.notNull(payment.getPaymentDescription(), "Missing payment description");
Boolean paymentResult = paymentService.makePayment(payment, loggedInUser);
SuccessResponseDTO successResponse = new SuccessResponseDTO();
successResponse.setSuccess(paymentResult);
return successResponse;
}
Can anyone shed light on the stack trace:
java.lang.AssertionError: Status expected:<200> but was:<415>
at org.springframework.test.util.AssertionErrors.fail(AssertionErrors.java:60)
at org.springframework.test.util.AssertionErrors.assertEquals(AssertionErrors.java:89)
at org.springframework.test.web.servlet.result.StatusResultMatchers$5.match(StatusResultMatchers.java:546)
at org.springframework.test.web.servlet.MockMvc$1.andExpect(MockMvc.java:141)
at com.capco.living.controller.PaymentControllerTest.createPaymentTest(PaymentControllerTest.java:69)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
HTTP Error 415 Unsupported media type - means that you send the data which is not supported by the service. In this case it means that you don't set the Content-Type header and actual content in the request. I suppose the JSON is expected content, so your call should look like this:
this.mockMvc.perform(post("/payment").contentType(MediaType.APPLICATION_JSON)
.content("{\"json\":\"request to be send\"}"))
.andExpect(status().isOk())
.and_the_rest_of_validation_part
You might also be missing some annotations on your controller class. Make sure you use #EnableWebMvc and #Controller
Check out this answer for details
Also you might add accept
mockMvc.perform(post("/api/sender/sms/")
.accept(MediaType.APPLICATION_JSON_UTF8)
.contentType(MediaType.APPLICATION_JSON_UTF8)
.content("{ \"serviceName\":\"serviceName\", \"apiId\":\"apiId\", \"to\":\"to\", \"msg\":\"msg\" }")
)
.andExpect(MockMvcResultMatchers.status().isOk())
.andReturn();