Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unit Testing with jUnit and Mockito for External REST API calls

I am building unit tests in a Spring Boot Java application for a service class.

The service class makes an external call to a REST API service that return a JSON response. I am mocking this call using Mockito. I am hardcoding a JSON in the mockserver response.

Is this bad practice to have hardcoded JSONs in your unit tests? If the JSON structure changes, then the test should fail is my reasoning. Is there a better, best practice where to do this?

Example Snippet below:

The actual code is functional, I just edited this snippet it for brevity to get the idea across, so post a comment if you see any errors:

    public class UserServiceTest extends TestCase {

    private static final String MOCK_URL = "baseUrl";
    private static final String DEFAULT_USER_ID = "353";

    UserService classUnderTest;
    ResponseEntity<Customer> mockResponseEntity;
    MockRestServiceServer mockServer;
    @Mock
    RestTemplate mockRestTemplate;

    public void setUp() throws Exception {
        super.setUp();

        classUnderTest = new UserRestService();
        mockRestTemplate = new RestTemplate();
        mockServer = MockRestServiceServer.createServer(mockRestTemplate);

        ReflectionTestUtils.setField(classUnderTest, "restTemplate",
                mockRestTemplate);
        ReflectionTestUtils.setField(classUnderTest, "userSvcUrl",
                MOCK_URL);
    }

    public void testGetUserById() throws Exception {

        mockServer.expect(requestTo(MOCK_URL + "/Users/" + DEFAULT_USER_ID)).andExpect(method(HttpMethod.GET))
                .andRespond(withSuccess(
                        "{\n" +
                                "    \"UserCredentials\": {\n" +
                                "        \"Password\": \"\",\n" +
                                "        \"PasswordNeedsUpdate\": false,\n" +
                                "        \"Security\": [\n" +
                                "            {\n" +
                                "                \"Answer\": \"\",\n" +
                                "                \"Question\": \"Why did the bicycle fall over?\"\n" +
                                "            }\n" +
                                "        ]\n" +
                                "}"
                        , MediaType.APPLICATION_JSON));


        Customer customer = classUnderTest.getUserById(DEFAULT_USER_ID);

        mockServer.verify();
        assertNotNull(customer);
        assertEquals(DEFAULT_USER_ID, customer.getId());
    }
}
like image 500
anataliocs Avatar asked May 14 '15 15:05

anataliocs


People also ask

Is Mockito used for unit testing?

Mockito is a mocking framework, JAVA-based library that is used for effective unit testing of JAVA applications. Mockito is used to mock interfaces so that a dummy functionality can be added to a mock interface that can be used in unit testing.

Can you unit test a REST API?

Unit tests are just one of many software testing methods for testing your REST APIs. They should be used wherever it is appropriate.

Is JUnit and Mockito are same?

JUnit is a framework that helps with writing and running your unit tests. Mockito (or any other mocking tool) is a framework that you specifically use to efficiently write certain kind of tests.


2 Answers

I am currently in the same boat as you and my reasoning was as follows: Creating a dummy JSON-response is like mocking an object and controlling it using Mockito.when. You would need to change anything in the when().thenReturn() call when you changed some inner parsing or you expect different results. This is the same with a JSON-response where calls are changed and object representations are altered.

Therefore my guess would be that this is fine. Reading various articles about testing REST API's, the general concensus is that creating dummy JSON-responses is good practice. Best practice would be to (from time to time) download the real JSON-response and insert this as the mocked response. This way you can keep your tests up-to-date with the external party, while the tests can run without internet requests.

Edit as requested:

  • Ruby - Stubbing external services,

  • Python - Testing a successful call

  • JavaScript - An example of AJAX testing

  • Python - Lastly a Google tutorial about mocking

like image 96
Tim van der Lippe Avatar answered Oct 03 '22 07:10

Tim van der Lippe


I would like to shine a light on another approach to consider, and that is to create POJO (e.g. data model, JavBean) of the object that the JSON represents then using a JSON serializer, like Gson from Google, to convert it to a JSON String.

UserCredentials uc = new UserCredentials ();
//set the values
Gson gson = new GsonBuilder().setPrettyPrinting().create();
String json = gson.toJson(uc);
like image 31
Jose Martinez Avatar answered Oct 03 '22 09:10

Jose Martinez