When writing integration tests for REST APIs in Spring Boot, it is common to use the org.springframework.boot.test.web.client.TestRestTemplate
. Anyone who has attempted to test the PATCH method with Spring Boot’s default TestRestTemplate will find out that it doesn’t ship with the ability to use the PATCH method.
As a workaround, org.apache.http.client.HttpClient
can be added as a substitute.
Add Apache HttpClient as a Dependency
Before you get started, you need to add the Apache HttpClient to your classpath manually or via build tool.
If you are using gradle, you can add the following to your build.gradle dependencies (Be sure to check the version).
dependencies {
compile('org.apache.httpcomponents:httpclient:4.5.3')
}
If you are using Maven, you can add it to your pom.xml:
org.apache.httpcomponents
httpclient
4.5.3
Use Apache’s HttpClient as a Substitute for TestRestTemplate
To highlight the implementation, I have added three steps in the code comments below.
import com.example.Repository.ContactRepository;
import com.example.model.Contact;
import org.apache.http.client.HttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.json.JSONObject;
import org.junit.After;
import org.junit.Before;
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.web.client.TestRestTemplate;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.web.client.RestTemplate;
import static junit.framework.TestCase.assertEquals;
import static org.junit.Assert.assertThat;
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class UpdateContactsTest {
// STEP #1
// Add the TestRestTemplate
@Autowired
private TestRestTemplate restTemplate;
private RestTemplate patchRestTemplate;
// END STEP #1
@Autowired
private ContactRepository contactRepository;
private Contact contact1;
@Before
public void setup() {
contact1 = contactRepository.saveAndFlush(new Contact("NotRyan", "McCormick", "555-555-5555"));
// STEP #2
// Add Apache HttpClient as TestRestTemplate
this.patchRestTemplate = restTemplate.getRestTemplate();
HttpClient httpClient = HttpClientBuilder.create().build();
this.patchRestTemplate.setRequestFactory(new HttpComponentsClientHttpRequestFactory(httpClient));
// End Step #2
}
@Test
public void updateContactOneWithPatch() throws Throwable {
String resourceUrl = "/api/v1/contacts/" + contact1.getId().toString();
// Create JSON Object
// { "firstName": "Ryan" }
JSONObject updateBody = new JSONObject();
updateBody.put("firstName", "Ryan");
// STEP #3
// Use patchRestTemplate to make call with PATCH method
ResponseEntity responseEntity =
patchRestTemplate.exchange(resourceUrl, HttpMethod.PATCH, getPostRequestHeaders(updateBody.toString()), Contact.class);
// Ensure Status Code is 200 OK
assertEquals(HttpStatus.OK, responseEntity.getStatusCode());
// Ensure Content-Type is application/json
assertEquals(MediaType.APPLICATION_JSON_UTF8, responseEntity.getHeaders().getContentType());
// Ensure that PATCH updated firstname
// from "NotRyan" to "Ryan"
Contact updatedContact = responseEntity.getBody();
assertEquals("Ryan", updatedContact.getFirstName());
assertEquals("McCormick", updatedContact.getLastName());
}
// Moved Over from TestHelper for Blog Post
public HttpEntity getPostRequestHeaders(String jsonPostBody) {
List acceptTypes = new ArrayList();
acceptTypes.add(MediaType.APPLICATION_JSON_UTF8);
HttpHeaders reqHeaders = new HttpHeaders();
reqHeaders.setContentType(MediaType.APPLICATION_JSON_UTF8);
reqHeaders.setAccept(acceptTypes);
return new HttpEntity(jsonPostBody, reqHeaders);
}
After setting up the TestRestTemplate like the example above, PATCH should now be available.
As always, please comment with questions, suggestions, improvements, etc…
Yes, it works!! Thanks a lot.