I'm new to unit testing and I want to test some jersey services in a project. We are using Junit. Please guide me to write test cases in better way.
CODE:
#GET
#Path("/getProducts/{companyID}/{companyName}/{date}")
#Produces(MediaType.APPLICATION_JSON)
public Object getProducts(#PathParam("companyID") final int companyID,
#PathParam("date") final String date, #PathParam("companyName") final String companyName)
throws IOException {
return productService.getProducts(companyID, companyName, date);
}
Above mentioned service is working fine and I want to write junit test case to test above mentioned method. Above method will retrieve list of products (List<Product>) in JSON format. I would like to write test case to check response status and json format.
NOTE: We are using Jersey 1.17.1 version.
Help would be appreciated :)
For Jersey web services testing there are several testing frameworks, namely: Jersey Test Framework (already mentioned in other answer - see here documentation for version 1.17 here: https://jersey.java.net/documentation/1.17/test-framework.html) and REST-Assured (https://code.google.com/p/rest-assured) - see here a comparison/setup of both (http://www.hascode.com/2011/09/rest-assured-vs-jersey-test-framework-testing-your-restful-web-services/).
I find the REST-Assured more interesting and powerful, but Jersey Test Framework is very easy to use too. In REST-Assured to write a test case "to check response status and json format" you could write the following test (very much like you do in jUnit):
package com.example.rest;
import static com.jayway.restassured.RestAssured.expect;
import groovyx.net.http.ContentType;
import org.junit.Before;
import org.junit.Test;
import com.jayway.restassured.RestAssured;
public class Products{
#Before
public void setUp(){
RestAssured.basePath = "http://localhost:8080";
}
#Test
public void testGetProducts(){
expect().statusCode(200).contentType(ContentType.JSON).when()
.get("/getProducts/companyid/companyname/12345088723");
}
}
This should do the trick for you... you can verify JSON specific elements also very easily and many other details. For instructions on more features you can check the very good guide from REST-Assured (https://code.google.com/p/rest-assured/wiki/Usage). Another good tutorial is this one http://www.hascode.com/2011/10/testing-restful-web-services-made-easy-using-the-rest-assured-framework/.
HTH.
Just ignore the annotations and write a normal unit test that passes the required parameters. The return I thought would usually be of type "javax.ws.rs.core.Response" ... There is a getEntity() method on that can be used. Using a Mock object framework like Mockito could be helpful in this case too.
Are you familiar with Chapter 26. Jersey Test Framework?
public class SimpleTest extends JerseyTest {
#Path("hello")
public static class HelloResource {
#GET
public String getHello() {
return "Hello World!";
}
}
#Override
protected Application configure() {
return new ResourceConfig(HelloResource.class);
}
#Test
public void test() {
final String hello = target("hello").request().get(String.class);
assertEquals("Hello World!", hello);
}
}
Related
I have multiple routes classes defined in my project under com.comp.myapp.routes.
For testing these I am mocking the end route and checking/comparing delivery received.
Say for example I have below routes:
public class MyRoute1 extends RouteBuilder {
public void configure() throws Exception {
//Route_1 code
}
}
public class MyRoute2 extends RouteBuilder {
public void configure() throws Exception {
//Route_2 code
}
}
....
...//some route impl
..
public class MyRouteN extends RouteBuilder {
public void configure() throws Exception {
//Route_N code
}
}
Now for all these routes the test case that I wrote seems same.
First mock it.
Mock for MyRoute1:
public class MyRoute1_Mock extends RouteBuilder {
public void configure() throws Exception {
from("direct:sampleInput")
.log("Received Message is ${body} and Headers are ${headers}")
.to("mock:output");
}
}
Test for MyRoute1:
public class MyRoute1_Test extends CamelTestSupport {
#Override
public RoutesBuilder createRouteBuilder() throws Exception {
return new MyRoute1_Mock();
}
#Test
public void sampleMockTest() throws InterruptedException {
String expected="Hello";
/**
* Producer Template.
*/
MockEndpoint mock = getMockEndpoint("mock:output");
mock.expectedBodiesReceived(expected);
String input="Hello";
template.sendBody("direct:sampleInput",input );
assertMockEndpointsSatisfied();
}
}
Now to make unit test for other classes just copy and paste the above code with different name say MyRoute2_Test , MyRoute3_Test , ...MyRouteN_Test.
So what did it actually tested?
It's just written for the purpose of writing test case.
It actually just checks/tests if mock library and camel-test library work or not Not our code works or not?
How should it actually be done?
You want to test your Camel routes but in the test you mock them away. So yes, you are testing your route mock instead of the real route.
To test your real routes:
Send a message to your real routes from endpoint
If this is not easy, mock your from endpoint (not the entire route!) by replacing it with a direct endpoint. This is quite easy with adviceWith
The test message is going through your route
Assert that any to endpoint receives the correct message by mocking these endpoints too. Again, use adviceWith for that. And Camel Mock of course
You can get the received messages (Exchanges) from a Camel Mock to do in depth assertions
If you got the happy test, start to write negative tests by injecting errors in your route. adviceWith can help here too
... and so on
If you are completely new to Camel route tests, get Camel in Action 2nd edition. It explains all mentioned testing aspects for Camel applications on 65 pages. And of course it also takes you on a complete ride through the Camel universe on much more pages.
By the way: if testing your routes is hard, they are too complex. Start to divide your routes so that they are easily testable.
The route you show doesn't really do anything to the messages traversing it, so testing that the same text you sent in one end comes out the other is all there is to test.
For routes with more data transformation and processing, you could test the output data types, that processors were called when needed, you could mock in throwing of exceptions, etc. What you have above is a good start on that.
Explained in-line,Hope this helps you understand significance of Mock in Unit Test:
public void sampleMockTest() throws InterruptedException {
String expected="Hello";
MockEndpoint mock = getMockEndpoint("mock:output");//Mocking endpoint
mock.expectedBodiesReceived(expected); //Setting expected output to mocked endpoint
String input="Hello";
template.sendBody("direct:sampleInput",input );//triggering route execution by sending input to route
assertMockEndpointsSatisfied(); //Verifies if input is equal to output
}
If your endpoint is Rest service you can make use of "TestRestTemplate" instead of Mocking it and Test like below:
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.test.context.junit4.SpringRunner;
#RunWith(SpringRunner.class)
#SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
public class SampleCamelApplicationTest {
}
import org.springframework.boot.test.web.client.TestRestTemplate;
#RunWith(SpringRunner.class)
#SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
public class SampleCamelApplicationTest {
#Autowired
private TestRestTemplate restTemplate;
}
#Test
public void sayHelloTest() {
// Call the REST API
ResponseEntity<String> response = restTemplate.getForEntity("/camel/hello", String.class);
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
String s = response.getBody();
assertThat(s.equals("Hello World"));
}
I have a Java class which contains API method
Ex:
#GET
#Path("/{id}")
public Resposce getIds(#PathParam(name) String name) {
//some code here
}
I want to right integration test for this API i.e while testing I want to call this method using path but not using method name
Have a look at Spring guides on their site:
Testing Web Layer
As you are explicitly asking for Spock: here is my standard implementation for an ApiSpec:
#SpringBootTest(webEnvironment = RANDOM_PORT)
abstract class AbstractServiceSpec extends Specification {
protected final static RestTestClient api = new RestTestClient()
#Value('http://localhost:${local.server.port}')
String serviceUrl
def setup() {
api.baseUrl = serviceUrl
}
def "GET /health should return 200"() {
expect:
api.get("/health").code() == 200
}
}
Note that RestTestClient is my own wrapper around OkHttp. You can use any HTTP client at hand of course.
The #SpringBootTest annotation makes Spring starting up the whole service. At the time your test gets executed, there service is fully up and running and you can black-box-test your API.
Generally Testing the Web Layer is a good read and most of it –as you can see in the example– can done in Spock as well as in JUnit.
This worked for me
import com.charter.aesd.testcommons.RESTSpecification
import groovyx.net.http.HttpResponseDecorator
class TestIT extends RESTSpecification{
def BASE_URL = "/test"
def "Get test"(){
when:
HttpResponseDecorator response = getRestClient().get([path:"$BASE_URL"+"/123"])
then:
response.status >=200 && response.status < 400
}
#Override
String getBaseUrl() {
return 'http://localhost:8889/'
}
}
Let's go straight to the problem:
I want to test a method that wants URL of Rest endpoint as a parameter. That method is using RestTemplate internally to send a request to that URL, so it needs to be full URL, for example http://localhost:8080/rest. Because of that I also have no way to mock RestTemplate.
I wanted to create simple #RestController but it seems that Spring is not creating endpoint when running tests.
I've tried creating MockMvc but it's not what I want. I have no way of getting the IP and port of MockMvc's created endpoint because no actual endpoint is created.
So, what I want is to make my #RestController accessible in tests by sending requests to URL, for example: http://localhost:8080/rest.
It's my first time creating a test like that, I will be grateful for your help. I was searching for an answer but I couldn't find a solution for my problem.
Edit:
Here's some code:
Unfortunately I can't post all the code but what I'm posting should be enough:
I have my endpoint like(names changed):
#RestController
public class EndpointController {
#RequestMapping(value = "/rest", method = RequestMethod.POST)
public List<Output> doSomething(#RequestBody Input[] requestList){
...
}
}
It's endpoint only for testing, it mimics the real endpoint. Then during my test I'm creating an object like:
new EndpointClient("http://localhost:8080/rest")
which has inside something like this:
ResponseEntity<Output[]> responseEntity = restTemplate.exchange(endpointURL,HttpMethod.POST, httpEntity, Output[].class);
Method having restTemplate request isn't called directly during testing(it's called by another method).
So I need to pass that URL to the Client object.
If you want to test your web application, checkout the Getting Started: Testing the Web Layer documentation.
Spring Boot is providing some useful annotations like #SpringBootTest, #AutoConfigureMockMvc, ...
See also the TestRestTemplate, which can be autowired to your WebMvcTest.
edit:
An example, copied from the documentation mentioned above:
package hello;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.boot.web.server.LocalServerPort;
import org.springframework.test.context.junit4.SpringRunner;
import static org.assertj.core.api.Assertions.assertThat;
#RunWith(SpringRunner.class)
#SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
public class HttpRequestTest {
#LocalServerPort
private int port;
#Autowired
private TestRestTemplate restTemplate;
#Test
public void greetingShouldReturnDefaultMessage() throws Exception {
assertThat(this.restTemplate.getForObject("http://localhost:" + port + "/",
String.class)).contains("Hello World");
}
}
I found a solution for my problem.
I did it with WireMock: http://wiremock.org/
First I had to create Transformer for my request, so the response depends on request, something like:
public class MyTransformer extends ResponseTransformer {
#Override
public Response transform(final Request request,
final Response response,
final FileSource fileSource,
final Parameters parameters){
HttpHeaders headers = new HttpHeaders(new HttpHeader("Content-Type", "application/json"));
if(request.getUrl().contains("/rest")){
...
return Response.Builder.like(response).but().body(...).headers(headers).build();
} else
return Response.Builder.like(response).but().status(404).headers(headers).build();
}
#Override
public String getName() {
return "swapper";
}
}
In my test I needed to put
WireMockServer server = new WireMockServer(wireMockConfig().port(3665).extensions("package.name.endpoint.MyTransformer"));
server.stubFor(post("/rest"));
It created exactly what I wanted. Code above is extremely simple, probably not that good and needs work but it shows the basics.
I am learning the library javax.ws.rs so I wrote a toy API.
For instance, I've got this POST method working. I've seen that there are many libraries for testing, like Jersey or Rest Assured, but, how can I unit test that response code is 200 and that the content is "hello"?
#POST
#Path("/getFoo")
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
Foo getFoo(#BeanParam final Foo foo)
{
return new Foo("hello");
}
For Jersey web services testing there are several testing frameworks, namely: Jersey Test Framework (https://jersey.java.net/documentation/1.17/test-framework.html) and REST-Assured (https://code.google.com/p/rest-assured) - see here a comparison/setup of both (http://www.hascode.com/2011/09/rest-assured-vs-jersey-test-framework-testing-your-restful-web-services/).
package com.example.rest;
import static com.jayway.restassured.RestAssured.expect;
import groovyx.net.http.ContentType;
import org.junit.Before;
import org.junit.Test;
import com.jayway.restassured.RestAssured;
public class Products{
#Before
public void setUp(){
RestAssured.basePath = "http://localhost:8080";
}
#Test
public void testGetProducts(){
expect().statusCode(200).contentType(ContentType.JSON).when()
.get("/getProducts/companyid/companyname/12345088723");
}
}
I'm new to using Mockito and am trying to understand a way to make a unit test of a class that relies on injected dependencies. What I want to do is to create mock objects of the dependencies and make the class that I am testing use those instead of the regular injected dependencies that would be injected by Spring. I have been reading tutorials but am a bit confused on how to do this.
I have one the class I want to test like this:
package org.rd.server.beans;
import org.springframework.beans.factory.annotation.Autowired;
public class TestBean1 {
#Autowired
private SubBean1 subBean1;
private String helloString;
public String testReturn () {
subBean1.setSomething("its working");
String something = subBean1.getSomething();
helloString = "Hello...... " + something;
return helloString;
}
Then I have the class that I want to use as a mock object (rather than the regular SubBean1 class, like below:
package org.rd.server.beans.mock;
public class SubBean1Mock {
private String something;
public String getSomething() {
return something;
}
public void setSomething(String something) {
this.something = something;
}
}
}
I just want to try running a simple test like this:
package test.rd.beans;
import org.rd.server.beans.TestBean1;
import junit.framework.*;
public class TestBean1Test extends TestCase
{
private TestBean1 testBean1;
public TestBean1Test(String name)
{
super(name);
}
public void setUp()
{
testBean1 = new TestBean1();
// Somehow inject the mock dependency SubBean1Mock ???
}
public void test1() {
assertEquals(testBean1.testReturn(),"working");
}
}
I figure there must be some fairly simple way to do this but I can't seem to understand the tutorials as I don't have the context yet to understand everything they are doing / explaining. If anyone could shed some light on this I would appreciate it.
If you're using Mockito you create mocks by calling Mockito's static mock method. You can then just pass in the mock to the class you're trying to test. Your setup method would look something like this:
testBean1 = new TestBean1();
SubBean1 subBeanMock = mock(SubBean1.class);
testBean1.setSubBean(subBeanMock);
You can then add the appropriate behavior to your mock objects for whatever you're trying to test with Mockito's static when method, for example:
when(subBeanMock.getSomething()).thenReturn("its working");
In Mockito you aren't really going to create new "mock" implementations, but rather you are going to mock out the methods on the interface of the injected dependency by telling Mockito what to return when the method is called.
I wrote a test of a Spring MVC Controller using Mockito and treated it just like any other java class. I was able to mock out the various other Spring beans I had and inject those using Spring's ReflectionTestUtils to pass in the Mockito based values. I wrote about it in my blog back in February. It has the full source for the test class and most of the source from the controller, so it's probably too long to put the contents here.
http://digitaljoel.nerd-herders.com/2011/02/05/mock-testing-spring-mvc-controller/
I stumbled on this thread while trying to set up some mocks for a slightly more complicated situation and figured I'd share my results for posterity.
My situation was similar in the fact that I needed to mock dependencies, but I also wanted to mock some of the methods on the class I was testing. This was the solution:
#MockBean
DependentService mockDependentService
ControllerToTest controllerToTest
#BeforeEach
public void setup() {
mockDependentService = mock(DependentService.class);
controllerToTest = mock(ControllerToTest.class);
ReflectionTestUtils.setField(controllerToTest, "dependantService", mockDependentService);
}
#Test
void test() {
//set up test and other mocks
//be sure to implement the below code that will call the real method that you are wanting to test
when(controllerToTest.methodToTest()).thenCallRealMethod();
//assertions
}
Note that "dependantService" needs to match whatever you have named the instance of the service on your controller. If that doesn't match the reflection will not find it and inject the mock for you.
This approach allows all the methods on the controller to be mocked by default, then you can specifically call out which method you want to use the real one. Then use the reflection to set any dependencies needed with the respective mock objects.
Hope this helps someone down the road as it stumped me for a while.