1

I have a GET API which accepts different parameters in controller class. According to the boolean parameter, the API should return a different result. How can I write JUnit test cases for the same?

@CrossOrigin

@RequestMapping(value = "/api/brand/multi-get", method = RequestMethod.GET, consumes =
        MediaType.APPLICATION_FORM_URLENCODED_VALUE, produces =
        MediaType.APPLICATION_JSON_VALUE)

public ResponseDTO listBrands(@RequestParam(required = false) Integer start,
                              @RequestParam(required = false) Integer limit,
                              @RequestParam(required = false) Boolean show_rejected) {

    ResponseDTO responseDTO = new ResponseDTO();
    System.out.println("------------------");
    try {
        if (start == null) {
            start = 0;
        }
        if (limit == null) {
            limit = 50;
        } else if (1 <= limit && limit <= 250) {
            if (show_rejected) {
                List<Brand> brands = brandService.findAllBrands(start, limit);
                if (brands != null && !brands.isEmpty()) {
                    responseDTO.setData(brands);
                    responseDTO.setCode(ErrorCode.error_0);
                    responseDTO.setMessage("Brand list");
                    return responseDTO;
                } else {
                    responseDTO.setData(new ArrayList<>());
                    responseDTO.setCode(ErrorCode.error_0);
                    responseDTO.setMessage("Brand list");
                    return responseDTO;
                }
            } else {
                Page<Brand> brands = brandService.findAllActiveBrands(start, limit);

                if (brands != null && !brands.isEmpty()) {
                    responseDTO.setData(brands);
                    responseDTO.setCode(ErrorCode.error_0);
                    responseDTO.setMessage("Brand list");
                    return responseDTO;
                } else {
                    responseDTO.setData(new ArrayList<>());
                    responseDTO.setCode(ErrorCode.error_0);
                    responseDTO.setMessage("Brand list");
                    return responseDTO;
                }
            }
        } else {
            responseDTO.setCode(ErrorCode.error_1104);
            responseDTO.setMessage(ErrorCode.error_msg1104);
            return responseDTO;
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
    return responseDTO;
}
anothernode
  • 5,100
  • 13
  • 43
  • 62
Chandana S
  • 23
  • 2
  • 5

3 Answers3

0

If you are using spring framework and mocking the tests, then the spring-test library contains the MockMvc and MockMvcRequestBuildersclasses, which can be used to test any APIs. You for GET API, you can build a request with public static MockHttpServletRequestBuilder get(String urlTemplate, Object... uriVars) method in MockMvcRequestBuilders

Then you can use public ResultActions perform(RequestBuilder requestBuilder) method in MockMvc for hitting the service.

ajith george
  • 538
  • 1
  • 5
  • 14
0

Invoke the GET API and assert for response details.

@Test
    public void postSimpleBody() throws Exception {
        Response response = server.newRequest("/path").request().buildPost(Entity.text("42")).invoke();
        assertEquals(Response.Status.OK.getStatusCode(), response.getStatus());
    }
Mebin Joe
  • 2,172
  • 4
  • 16
  • 22
0

First of all you have to annotate your tests class with the following annotations:

@SpringBootTest
@RunWith(SpringRunner.class)
@AutoConfigureMockMvc

If you have authentication add:

@WithMockUser

Autowire the mockMvc to perform the requests:

@Autowired
private MockMvc mockMvc;

Use @MockBean to mock the service layer:

@MockBean
private BrandService brandService;

And annotate your test with the @Test annotation:

@Test
public void test_listBrands_when_something_do_something() {
}

Then using Mockito, mock the method in the service covered by your test:

List<Brand> mockBrands = new LinkedList<Brand>();
mockBrands.add(new Brand(/*...*/));

Mockito.when(brandService.findAllBrands(0, 25)).thenReturn(mockBrands);

Create the requestBuilder using the class org.springframework.test.web.servlet.request.MockMvcRequestBuilders:

MockHttpServletRequestBuilder requestBuilder = MockMvcRequestBuilders.get("/api/brand/multi-get?start={0}&limit={1}&show_rejected={2}", 0, 25, true)
    .accept(MediaType.APPLICATION_JSON);

Perform the request and assert the results using the class org.springframework.test.web.servlet.result.MockMvcResultMatchers:

mockMvc.perform(requestBuilder)
    .andExpect(MockMvcResultMatchers.status().isOk())
    .andExpect(MockMvcResultMatchers.content().contentType(MediaType.APPLICATION_JSON));

As a final tip, add this 2 static imports so your code will be shorter:

import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;

Then you can do get(), post(), status(), content(), etc

Here is the full example:

import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;

@SpringBootTest
@RunWith(SpringRunner.class)
@AutoConfigureMockMvc
public class MyApiControllerTests {
    @Autowired
    private MockMvc mockMvc;

    @MockBean
    private BrandService brandService;

    @Test
    public void test_listBrands_when_something_do_something() {
        //#region Mocks
        List<Brand> mockBrands = new LinkedList<Brand>();
        mockBrands.add(new Brand(/*...*/));

        Mockito.when(brandService.findAllBrands(0, 25)).thenReturn(mockBrands);
        //#endregion

        MockHttpServletRequestBuilder requestBuilder = get("/api/brand/multi-get?start={0}&limit={1}&show_rejected={2}", 0, 25, true).accept(MediaType.APPLICATION_JSON);

        mockMvc.perform(requestBuilder)
            .andExpect(status().isOk())
            .andExpect(content().contentType(MediaType.APPLICATION_JSON));

    }

}
Fabian Mendez
  • 512
  • 5
  • 15
  • Its showing an error on ".andExpect(status().isOk()) .andExpect(content().contentType(MediaType.APPLICATION_JSON));" Since it is a GET API ,we should give "APPLICATION_FORM_URLENCODED" instead of "APPLICATION_JSON" Right? But when I give "APPLICATION_FORM_URLENCODED" it is showing the same error on ".andExpect(status().isOk()) .andExpect(content().contentType(MediaType.APPLICATION_JSON));" – Chandana S Jan 31 '19 at 04:30
  • The problem is: One I posted above and.. -> First of all I have to write test case for if(show rejected) condition, then only it will enter in to "List brands = brandService.findAllBrands(start, limit);". How should I write the test case to test if(show rejected ) condition. -> How to write test case for the else condition when it returnd a "Page" other than List of Brands. – Chandana S Jan 31 '19 at 04:54
  • `.accept(MediaType.APPLICATION_JSON)` indicates that you expect the api to return a json and then you validate this using `.andExpect(content().contentType(MediaType.APPLICATION_JSON))` – Fabian Mendez Jan 31 '19 at 13:30
  • And sorry I forgot to write an example to show you how to pass parameters to as form url encoded. I will edit the answer – Fabian Mendez Jan 31 '19 at 13:31
  • Done!. Now you can test each path of your code, keep in mind that you should create a method for each test and only mock the service when it is reached by the test – Fabian Mendez Jan 31 '19 at 13:44