简体   繁体   中英

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());
    }
}

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:

I would like to shine a light on another approach to consider, and that is to create POJO (eg 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);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM