[BAEL-11597] Move and update Etags article
* Moved etags article related code * Fixed existing etag Ignored test * Added etag scentsio adding etag support to a single endpoint * Added tests for single endpoint etag scenario * Cleaned now unused code in spring-rest-full module
This commit is contained in:
@@ -1,21 +1,28 @@
|
||||
package com.baeldung.common.web;
|
||||
|
||||
import static com.baeldung.web.util.HTTPLinkHeaderUtil.extractURIByRel;
|
||||
import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic;
|
||||
import static org.apache.commons.lang3.RandomStringUtils.randomNumeric;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.baeldung.persistence.model.Foo;
|
||||
import com.google.common.net.HttpHeaders;
|
||||
|
||||
import io.restassured.RestAssured;
|
||||
import io.restassured.http.ContentType;
|
||||
import io.restassured.response.Response;
|
||||
|
||||
public abstract class AbstractBasicLiveTest<T extends Serializable> extends AbstractLiveTest<T> {
|
||||
@@ -97,7 +104,82 @@ public abstract class AbstractBasicLiveTest<T extends Serializable> extends Abst
|
||||
final String uriToNextPage = extractURIByRel(response.getHeader(HttpHeaders.LINK), "next");
|
||||
assertNull(uriToNextPage);
|
||||
}
|
||||
|
||||
// etags
|
||||
|
||||
// count
|
||||
@Test
|
||||
public void givenResourceExists_whenRetrievingResource_thenEtagIsAlsoReturned() {
|
||||
// Given
|
||||
final String uriOfResource = createAsUri();
|
||||
|
||||
// When
|
||||
final Response findOneResponse = RestAssured.given()
|
||||
.header("Accept", "application/json")
|
||||
.get(uriOfResource);
|
||||
|
||||
// Then
|
||||
assertNotNull(findOneResponse.getHeader(HttpHeaders.ETAG));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenResourceWasRetrieved_whenRetrievingAgainWithEtag_thenNotModifiedReturned() {
|
||||
// Given
|
||||
final String uriOfResource = createAsUri();
|
||||
final Response findOneResponse = RestAssured.given()
|
||||
.header("Accept", "application/json")
|
||||
.get(uriOfResource);
|
||||
final String etagValue = findOneResponse.getHeader(HttpHeaders.ETAG);
|
||||
|
||||
// When
|
||||
final Response secondFindOneResponse = RestAssured.given()
|
||||
.header("Accept", "application/json")
|
||||
.headers("If-None-Match", etagValue)
|
||||
.get(uriOfResource);
|
||||
|
||||
// Then
|
||||
assertTrue(secondFindOneResponse.getStatusCode() == 304);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenResourceWasRetrievedThenModified_whenRetrievingAgainWithEtag_thenResourceIsReturned() {
|
||||
// Given
|
||||
final String uriOfResource = createAsUri();
|
||||
final Response firstFindOneResponse = RestAssured.given()
|
||||
.header("Accept", "application/json")
|
||||
.get(uriOfResource);
|
||||
final String etagValue = firstFindOneResponse.getHeader(HttpHeaders.ETAG);
|
||||
final long createdId = firstFindOneResponse.jsonPath().getLong("id");
|
||||
|
||||
Foo updatedFoo = new Foo("updated value");
|
||||
updatedFoo.setId(createdId);
|
||||
Response updatedResponse = RestAssured.given().contentType(ContentType.JSON).body(updatedFoo)
|
||||
.put(uriOfResource);
|
||||
assertThat(updatedResponse.getStatusCode() == 200);
|
||||
|
||||
// When
|
||||
final Response secondFindOneResponse = RestAssured.given()
|
||||
.header("Accept", "application/json")
|
||||
.headers("If-None-Match", etagValue)
|
||||
.get(uriOfResource);
|
||||
|
||||
// Then
|
||||
assertTrue(secondFindOneResponse.getStatusCode() == 200);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore("Not Yet Implemented By Spring - https://jira.springsource.org/browse/SPR-10164")
|
||||
public void givenResourceExists_whenRetrievedWithIfMatchIncorrectEtag_then412IsReceived() {
|
||||
// Given
|
||||
final String uriOfResource = createAsUri();
|
||||
|
||||
// When
|
||||
final Response findOneResponse = RestAssured.given()
|
||||
.header("Accept", "application/json")
|
||||
.headers("If-Match", randomAlphabetic(8))
|
||||
.get(uriOfResource);
|
||||
|
||||
// Then
|
||||
assertTrue(findOneResponse.getStatusCode() == 412);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+116
@@ -0,0 +1,116 @@
|
||||
package com.baeldung.web;
|
||||
|
||||
import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.ResultActions;
|
||||
|
||||
import com.baeldung.persistence.model.Foo;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.google.common.net.HttpHeaders;
|
||||
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest
|
||||
@AutoConfigureMockMvc(addFilters = false)
|
||||
public class FooControllerCustomEtagIntegrationTest {
|
||||
|
||||
@Autowired
|
||||
private MockMvc mvc;
|
||||
|
||||
private String FOOS_ENDPOINT = "/auth/foos/";
|
||||
private String CUSTOM_ETAG_ENDPOINT_SUFFIX = "/custom-etag";
|
||||
|
||||
private static String serializeFoo(Foo foo) throws Exception {
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
return mapper.writeValueAsString(foo);
|
||||
}
|
||||
|
||||
private static String createFooJson() throws Exception {
|
||||
return serializeFoo(new Foo(randomAlphabetic(6)));
|
||||
}
|
||||
|
||||
private static Foo deserializeFoo(String fooJson) throws Exception {
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
return mapper.readValue(fooJson, Foo.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenResourceExists_whenRetrievingResourceUsingCustomEtagEndpoint_thenEtagIsAlsoReturned()
|
||||
throws Exception {
|
||||
// Given
|
||||
String createdResourceUri = this.mvc.perform(post(FOOS_ENDPOINT).contentType(MediaType.APPLICATION_JSON)
|
||||
.content(createFooJson()))
|
||||
.andExpect(status().isCreated())
|
||||
.andReturn()
|
||||
.getResponse()
|
||||
.getHeader(HttpHeaders.LOCATION);
|
||||
|
||||
// When
|
||||
ResultActions result = this.mvc
|
||||
.perform(get(createdResourceUri + CUSTOM_ETAG_ENDPOINT_SUFFIX).contentType(MediaType.APPLICATION_JSON));
|
||||
|
||||
// Then
|
||||
result.andExpect(status().isOk())
|
||||
.andExpect(header().string(HttpHeaders.ETAG, "\"0\""));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenResourceWasRetrieved_whenRetrievingAgainWithEtagUsingCustomEtagEndpoint_thenNotModifiedReturned() throws Exception {
|
||||
// Given
|
||||
String createdResourceUri = this.mvc.perform(post(FOOS_ENDPOINT).contentType(MediaType.APPLICATION_JSON)
|
||||
.content(createFooJson()))
|
||||
.andExpect(status().isCreated())
|
||||
.andReturn()
|
||||
.getResponse()
|
||||
.getHeader(HttpHeaders.LOCATION);
|
||||
ResultActions findOneResponse = this.mvc
|
||||
.perform(get(createdResourceUri + CUSTOM_ETAG_ENDPOINT_SUFFIX).contentType(MediaType.APPLICATION_JSON));
|
||||
String etag = findOneResponse.andReturn().getResponse().getHeader(HttpHeaders.ETAG);
|
||||
|
||||
// When
|
||||
ResultActions result = this.mvc
|
||||
.perform(get(createdResourceUri + CUSTOM_ETAG_ENDPOINT_SUFFIX).contentType(MediaType.APPLICATION_JSON).header(HttpHeaders.IF_NONE_MATCH, etag));
|
||||
|
||||
// Then
|
||||
result.andExpect(status().isNotModified());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenResourceWasRetrievedThenModified_whenRetrievingAgainWithEtagUsingCustomEtagEndpoint_thenResourceIsReturned() throws Exception {
|
||||
// Given
|
||||
String createdResourceUri = this.mvc.perform(post(FOOS_ENDPOINT).contentType(MediaType.APPLICATION_JSON)
|
||||
.content(createFooJson()))
|
||||
.andExpect(status().isCreated())
|
||||
.andReturn()
|
||||
.getResponse()
|
||||
.getHeader(HttpHeaders.LOCATION);
|
||||
ResultActions findOneResponse = this.mvc
|
||||
.perform(get(createdResourceUri + CUSTOM_ETAG_ENDPOINT_SUFFIX).contentType(MediaType.APPLICATION_JSON));
|
||||
String etag = findOneResponse.andReturn().getResponse().getHeader(HttpHeaders.ETAG);
|
||||
Foo createdFoo = deserializeFoo(findOneResponse.andReturn().getResponse().getContentAsString());
|
||||
createdFoo.setName("updated name");
|
||||
this.mvc
|
||||
.perform(put(createdResourceUri).contentType(MediaType.APPLICATION_JSON).content(serializeFoo(createdFoo)));
|
||||
|
||||
// When
|
||||
ResultActions result = this.mvc
|
||||
.perform(get(createdResourceUri + CUSTOM_ETAG_ENDPOINT_SUFFIX).contentType(MediaType.APPLICATION_JSON).header(HttpHeaders.IF_NONE_MATCH, etag));
|
||||
|
||||
// Then
|
||||
result.andExpect(status().isOk())
|
||||
.andExpect(header().string(HttpHeaders.ETAG, "\"1\""));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -8,8 +8,8 @@ import org.junit.runners.Suite;
|
||||
@Suite.SuiteClasses({
|
||||
// @formatter:off
|
||||
FooDiscoverabilityLiveTest.class,
|
||||
FooLiveTest.class
|
||||
,FooPageableLiveTest.class
|
||||
FooLiveTest.class,
|
||||
FooPageableLiveTest.class
|
||||
}) //
|
||||
public class LiveTestSuiteLiveTest {
|
||||
|
||||
|
||||
Reference in New Issue
Block a user