diff --git a/.gitignore b/.gitignore
index 32858aa..6f8df1c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -10,3 +10,8 @@
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
+
+# Eclipse
+.classpath
+.project
+.settings
diff --git a/README.md b/README.md
index 2fa877e..0d11695 100644
--- a/README.md
+++ b/README.md
@@ -203,7 +203,7 @@ Please follow the steps below:
Payara Micro is enough to run
3. Run the command: "mvn install" in the root folder of the distributionfolder.
4. Run the blog-web
- > java -jar payara-micro-4.1.152.1.jar --deploy blog-web\target\blog-web.war
+ > java -jar payara-micro-5.2021.8.jar --deploy blog-web\target\blog-web.war
5. Go to address: http://localhost:8080/blog-web/hello-pierce. The server should respond with a text that reads: {"message":"Hello Pierce"}.
6. Now basic environment and Blog Ping project is installed correctly.
@@ -214,7 +214,7 @@ Please follow the steps below:
The integration tests is (and should be) located under the maven artifact "integration test".
These tests should test the expected behavior of a correct implementation of Blog posts.
-There is a simple test to start with. You run the test with "mvn test-Dtest =*TestIntegr" .
+There is a simple test to start with. You run the test with "mvn test -Dtest=*TestIntegr" .
The tests and flow is a suggestion and may not use the most convinient APIs to do it, you may change.
You should fill in with extra tests (and expect that we do to ;) )
diff --git a/blog-web/.gitignore b/blog-web/.gitignore
new file mode 100644
index 0000000..b83d222
--- /dev/null
+++ b/blog-web/.gitignore
@@ -0,0 +1 @@
+/target/
diff --git a/blog-web/pom.xml b/blog-web/pom.xml
index 8ec9481..38514ce 100644
--- a/blog-web/pom.xml
+++ b/blog-web/pom.xml
@@ -7,7 +7,7 @@
1.0-SNAPSHOT
- com.pierceecom.sample
+ com.pierceecom.sample.web
blog-web
1.0-SNAPSHOT
war
@@ -19,6 +19,21 @@
+
+ io.swagger
+ swagger-annotations
+ 1.6.2
+
+
+ io.swagger
+ swagger-jaxrs
+ 1.6.3
+
+
+ com.fasterxml.jackson.core
+ jackson-annotations
+ 2.13.0
+
javax
javaee-api
@@ -30,11 +45,22 @@
test
- org.glassfish.jersey.core
- jersey-client
- 2.17
- test
-
+ com.sun.jersey
+ jersey-client
+ 1.12
+
+
+ org.mockito
+ mockito-core
+ 4.0.0
+ test
+
+
+ org.hamcrest
+ hamcrest-core
+ 2.2
+ test
+
@@ -58,6 +84,31 @@
+
+ org.openapitools
+ openapi-generator-maven-plugin
+ 5.2.0
+
+
+
+ generate
+
+
+ ${project.basedir}/src/main/java/com/pierceecom/resources/PostsApi.yaml
+ jaxrs-resteasy-eap
+
+ com.pierceecom.blog.swagger
+ com.pierceecom.blog.model
+ true
+ false
+
+ src/gen/java/main
+ true
+
+
+
+
+
diff --git a/blog-web/src/main/java/com/pierceecom/blog/AccessControlResponseFilter.java b/blog-web/src/main/java/com/pierceecom/blog/AccessControlResponseFilter.java
new file mode 100644
index 0000000..d390bc9
--- /dev/null
+++ b/blog-web/src/main/java/com/pierceecom/blog/AccessControlResponseFilter.java
@@ -0,0 +1,31 @@
+package com.pierceecom.blog;
+
+import java.io.IOException;
+
+import javax.annotation.Priority;
+import javax.ws.rs.container.ContainerRequestContext;
+import javax.ws.rs.container.ContainerResponseContext;
+import javax.ws.rs.container.ContainerResponseFilter;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.ext.Provider;
+import javax.ws.rs.Priorities;
+
+/**
+ * This is a response filter class to add CORS headers in the response.
+ * So that other applications (e.g. Angular application) can access resources from this web service resources.
+ */
+
+@Provider
+@Priority(Priorities.HEADER_DECORATOR)
+public class AccessControlResponseFilter implements ContainerResponseFilter {
+
+ @Override
+ public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) throws IOException {
+ final MultivaluedMap headers = responseContext.getHeaders();
+ headers.add("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
+ headers.add("Access-Control-Allow-Origin", "*");
+ if (requestContext.getMethod().equalsIgnoreCase("OPTIONS")) {
+ headers.add("Access-Control-Allow-Headers", requestContext.getHeaderString("Access-Control-Request-Headers"));
+ }
+ }
+}
\ No newline at end of file
diff --git a/blog-web/src/main/java/com/pierceecom/blog/JAXRSConfiguration.java b/blog-web/src/main/java/com/pierceecom/blog/JAXRSConfiguration.java
index 96a0744..f04a44f 100644
--- a/blog-web/src/main/java/com/pierceecom/blog/JAXRSConfiguration.java
+++ b/blog-web/src/main/java/com/pierceecom/blog/JAXRSConfiguration.java
@@ -5,11 +5,16 @@
import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;
+import com.pierceecom.blog.api.PostsApiImpl;
+
+
@ApplicationPath("/")
public class JAXRSConfiguration extends Application {
@Override
public Set> getClasses() {
HashSet> classes = new HashSet<>();
+ classes.add(AccessControlResponseFilter.class);
+ classes.add(PostsApiImpl.class);
classes.add(HelloPierceResource.class);
return classes;
}
diff --git a/blog-web/src/main/java/com/pierceecom/blog/api/PostsApiImpl.java b/blog-web/src/main/java/com/pierceecom/blog/api/PostsApiImpl.java
new file mode 100644
index 0000000..1051f4e
--- /dev/null
+++ b/blog-web/src/main/java/com/pierceecom/blog/api/PostsApiImpl.java
@@ -0,0 +1,91 @@
+package com.pierceecom.blog.api;
+
+import java.util.Optional;
+import java.util.concurrent.atomic.AtomicLong;
+
+import javax.inject.Inject;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.SecurityContext;
+
+import com.pierceecom.blog.model.Post;
+import com.pierceecom.blog.service.PostService;
+import com.pierceecom.blog.swagger.PostsApi;
+
+public class PostsApiImpl implements PostsApi{
+
+ private static final AtomicLong postSequenceId = new AtomicLong();
+ private static final String VALID_XML_CONTENT_REGEX = "[\\u0009\\u000a\\u000d\\u0020-\\uD7FF\\uE000-\\uFFFD]+$"; // regex to match valid XML Characters.
+ private static final int TITLE_MAX_LENGTH = 40;
+ private static final int CONTENT_MAX_LENGTH = 100;
+
+ private PostService postService;
+
+ @Inject
+ public PostsApiImpl(PostService postService) {
+ this.postService = postService;
+ }
+
+ @Override
+ public Response addPost(Post post, SecurityContext securityContext) {
+ if (!hasValidPostContent(post) || !isNullOrEmpty(post.getId())) {
+ return Response.status(Response.Status.BAD_REQUEST).build();
+ }
+ post.setId(Long.toString(postSequenceId.incrementAndGet()));
+ postService.addPost(post);
+ return Response.status(Response.Status.CREATED).entity(post).build();
+ }
+
+ @Override
+ public Response deletePost(String postId, SecurityContext securityContext) {
+ Optional optPost = postService.getPostById(postId);
+ if (optPost.isEmpty()) {
+ return Response.status(Response.Status.NOT_FOUND).build();
+ }
+ postService.deletePost(postId);
+ return Response.ok().build();
+ }
+
+ @Override
+ public Response getAllPosts(SecurityContext securityContext) {
+ return Response.ok(postService.getAllPosts()).build();
+ }
+
+ @Override
+ public Response getPostById(String postId, SecurityContext securityContext) {
+ Optional optPost = postService.getPostById(postId);
+ if (optPost.isEmpty()) {
+ return Response.status(Response.Status.NO_CONTENT).build();
+ }
+ return Response.ok(optPost.get()).build();
+ }
+
+ @Override
+ public Response updatePost(Post post, SecurityContext securityContext) {
+ if (isNullOrEmpty(post.getId()) || !hasValidPostContent(post)) {
+ return Response.status(Response.Status.BAD_REQUEST).build();
+ }
+ Optional optPost = postService.getPostById(post.getId());
+ if (optPost.isEmpty()) {
+ return Response.status(Response.Status.NOT_FOUND).build();
+ }
+ postService.updatePost(post);
+ return Response.status(Response.Status.CREATED).entity(post).build();
+ }
+
+ private boolean isNullOrEmpty(String s) {
+ if (s == null) {
+ return true;
+ }
+ return s.isBlank();
+ }
+
+ private boolean hasValidPostContent(Post post) {
+ if (!post.getTitle().matches(VALID_XML_CONTENT_REGEX) || !post.getContent().matches(VALID_XML_CONTENT_REGEX)) {
+ return false;
+ }
+ if (post.getTitle().length() > TITLE_MAX_LENGTH || post.getContent().length() > CONTENT_MAX_LENGTH) {
+ return false;
+ }
+ return true;
+ }
+}
diff --git a/blog-web/src/main/java/com/pierceecom/blog/service/PostService.java b/blog-web/src/main/java/com/pierceecom/blog/service/PostService.java
new file mode 100644
index 0000000..74d7816
--- /dev/null
+++ b/blog-web/src/main/java/com/pierceecom/blog/service/PostService.java
@@ -0,0 +1,20 @@
+package com.pierceecom.blog.service;
+
+import java.util.Collection;
+import java.util.Optional;
+
+import com.pierceecom.blog.model.Post;
+
+public interface PostService {
+
+ void addPost(Post post);
+
+ void deletePost(String postId);
+
+ Collection getAllPosts();
+
+ Optional getPostById(String postId);
+
+ void updatePost(Post post);
+
+}
diff --git a/blog-web/src/main/java/com/pierceecom/blog/service/PostServiceImpl.java b/blog-web/src/main/java/com/pierceecom/blog/service/PostServiceImpl.java
new file mode 100644
index 0000000..1d514c4
--- /dev/null
+++ b/blog-web/src/main/java/com/pierceecom/blog/service/PostServiceImpl.java
@@ -0,0 +1,45 @@
+package com.pierceecom.blog.service;
+
+import java.util.Collection;
+import java.util.Optional;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+import javax.enterprise.context.ApplicationScoped;
+
+import com.pierceecom.blog.model.Post;
+
+@ApplicationScoped
+public class PostServiceImpl implements PostService {
+
+ private ConcurrentMap postMap = new ConcurrentHashMap<>();
+
+ protected PostServiceImpl() {
+ }
+
+ @Override
+ public void addPost(Post post) {
+ postMap.put(post.getId(), post);
+ }
+
+ @Override
+ public void deletePost(String postId) {
+ postMap.remove(postId);
+ }
+
+ @Override
+ public Collection getAllPosts() {
+ return postMap.values();
+ }
+
+ @Override
+ public Optional getPostById(String postId) {
+ return Optional.ofNullable(postMap.get(postId));
+ }
+
+ @Override
+ public void updatePost(Post post) {
+ postMap.put(post.getId(), post);
+ }
+
+}
diff --git a/blog-web/src/main/java/com/pierceecom/resources/PostsApi.yaml b/blog-web/src/main/java/com/pierceecom/resources/PostsApi.yaml
new file mode 100644
index 0000000..064417a
--- /dev/null
+++ b/blog-web/src/main/java/com/pierceecom/resources/PostsApi.yaml
@@ -0,0 +1,129 @@
+swagger: "2.0"
+info:
+ description: "This is the definition of the API for code test as Pierce AB"
+ version: "1.0.0"
+ title: "Simple blog post API"
+host: "localhost:8080"
+basePath: "/blog-web"
+schemes:
+- "http"
+paths:
+ /posts:
+ get:
+ tags:
+ - "post"
+ summary: "Get all posts"
+ description: "Returns all posts"
+ operationId: "getAllPosts"
+ produces:
+ - "application/json"
+ responses:
+ 200:
+ description: "successful operation"
+ schema:
+ $ref: "#/definitions/Post"
+ post:
+ tags:
+ - "post"
+ summary: "Add a new post"
+ description: ""
+ operationId: "addPost"
+ consumes:
+ - "application/json"
+ produces:
+ - "application/json"
+ parameters:
+ - in: "body"
+ name: "body"
+ description: "Post object that needs to be added"
+ required: true
+ schema:
+ $ref: "#/definitions/Post"
+ responses:
+ 201:
+ description: "OK of post"
+ schema:
+ $ref: "#/definitions/Post"
+ 405:
+ description: "Invalid input"
+ put:
+ tags:
+ - "post"
+ summary: "Updates a post"
+ description: ""
+ operationId: "updatePost"
+ consumes:
+ - "application/json"
+ produces:
+ - "application/json"
+ parameters:
+ - in: "body"
+ name: "body"
+ description: "Post object that needs to be updated"
+ required: true
+ schema:
+ $ref: "#/definitions/Post"
+ responses:
+ 201:
+ description: "OK of post"
+ schema:
+ $ref: "#/definitions/Post"
+ 404:
+ description: "Post not found"
+ 405:
+ description: "Invalid input"
+ /posts/{postId}:
+ get:
+ tags:
+ - "post"
+ summary: "Find post by ID"
+ description: "Returns a single post"
+ operationId: "getPostById"
+ produces:
+ - "application/json"
+ parameters:
+ - name: "postId"
+ in: "path"
+ description: "ID of post to return"
+ required: true
+ type: "string"
+ responses:
+ 200:
+ description: "successful operation"
+ schema:
+ $ref: "#/definitions/Post"
+ 204:
+ description: "No content"
+ delete:
+ tags:
+ - "post"
+ summary: "Deletes a post"
+ description: ""
+ operationId: "deletePost"
+ parameters:
+ - name: "postId"
+ in: "path"
+ description: "Post id to delete"
+ required: true
+ type: "string"
+ responses:
+ 200:
+ description: "successful operation"
+ 404:
+ description: "Post not found"
+definitions:
+ Post:
+ type: "object"
+ required:
+ - "title"
+ - "content"
+ properties:
+ id:
+ type: "string"
+ example: "1"
+ title:
+ type: "string"
+ example: "what I did today"
+ content:
+ type: "string"
+ example: "wrote a boring post"
\ No newline at end of file
diff --git a/blog-web/src/test/java/com/pierceecom/blog/api/PostsApiTest.java b/blog-web/src/test/java/com/pierceecom/blog/api/PostsApiTest.java
new file mode 100644
index 0000000..54ceca8
--- /dev/null
+++ b/blog-web/src/test/java/com/pierceecom/blog/api/PostsApiTest.java
@@ -0,0 +1,140 @@
+package com.pierceecom.blog.api;
+
+import javax.ws.rs.core.Response;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import com.pierceecom.blog.model.Post;
+import com.pierceecom.blog.service.PostService;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+import java.util.Optional;
+
+public class PostsApiTest {
+
+ private PostService postService;
+ private PostsApiImpl postsApi;
+
+ @Before
+ public void setup() {
+ postService = mock(PostService.class);
+ postsApi = new PostsApiImpl(postService);
+ }
+
+ @Test
+ public void test_1_0_AddPost_Ok() {
+ Post post = samplePost("","Valid post","It's valid post!");
+ Response response = postsApi.addPost(post, null);
+ assertEquals(response.getStatus(),Response.Status.CREATED.getStatusCode());
+ assertEquals((Post)response.getEntity(), post);
+ }
+
+ @Test
+ public void test_1_1_AddPost_TitleLengthMoreThanTwenty() {
+ Post post = samplePost("","Trying to add a post's title more than 20 characters","It's invalid post!");
+ Response response = postsApi.addPost(post, null);
+ assertEquals(response.getStatus(),Response.Status.BAD_REQUEST.getStatusCode());
+ }
+
+ @Test
+ public void test_1_2_AddPost_BadRequest() {
+ Post post = samplePost("1","Trying to create a post with Id!","Id is auto generated field. So it's invalid post!");
+ Response response = postsApi.addPost(post, null);
+ assertEquals(response.getStatus(),Response.Status.BAD_REQUEST.getStatusCode());
+ }
+
+ @Test
+ public void test_1_3_AddPost_WithInvalidChar() {
+ Post post = samplePost("","Content with invalid emoji character","It contains invalid char 😦");
+ Response response = postsApi.addPost(post, null);
+ assertEquals(response.getStatus(),Response.Status.BAD_REQUEST.getStatusCode());
+ }
+
+ @Test
+ public void test_2_0_DeletePost_Ok() {
+ Post post = samplePost("3","Delete Post","Post to be deleted!");
+ when(postService.getPostById(post.getId())).thenReturn(Optional.of(post));
+ Response response = postsApi.deletePost(post.getId(), null);
+ assertEquals(response.getStatus(),Response.Status.OK.getStatusCode());
+ }
+
+ @Test
+ public void test_2_1_DeletePost_NotFound() {
+ Post post = samplePost("4","Delete Post","Post to be deleted!");
+ when(postService.getPostById(post.getId())).thenReturn(Optional.of(post));
+ Response response = postsApi.deletePost("100", null);
+ assertEquals(response.getStatus(),Response.Status.NOT_FOUND.getStatusCode());
+ }
+
+ @Test
+ public void test_3_0_GetAllPosts_Ok() {
+ Post post1 = samplePost("5","Post 1","Getting all post1!");
+ Post post2 = samplePost("6","Post 2","Getting all post2!");
+ Collection postList = Arrays.asList(post1, post2);
+ when(postService.getAllPosts()).thenReturn(postList);
+ Response response = postsApi.getAllPosts(null);
+ assertEquals(response.getStatus(),Response.Status.OK.getStatusCode());
+ Collection returnedList = (Collection) response.getEntity();
+ assertEquals(returnedList.size(),2);
+ }
+
+ @Test
+ public void test_3_1_GetAllPosts_WithOutData() {
+ when(postService.getAllPosts()).thenReturn(List.of());
+ Response response = postsApi.getAllPosts(null);
+ assertEquals(response.getStatus(),Response.Status.OK.getStatusCode());
+ Collection returnedList =(Collection) response.getEntity();
+ assertEquals(returnedList.size(),0);
+ }
+
+ @Test
+ public void test_4_0_GetPostById_Ok() {
+ Post post = samplePost("7","Get Post","Getting post by ID!");
+ when(postService.getPostById(post.getId())).thenReturn(Optional.of(post));
+ Response response = postsApi.getPostById(post.getId(), null);
+ assertEquals(response.getStatus(),Response.Status.OK.getStatusCode());
+ assertEquals((Post)response.getEntity(), post);
+ }
+
+ @Test
+ public void test_4_1_GetPostById_NoContent() {
+ when(postService.getPostById(anyString())).thenReturn(Optional.empty());
+ Response response = postsApi.getPostById(anyString(), null);
+ assertEquals(response.getStatus(),Response.Status.NO_CONTENT.getStatusCode());
+ }
+
+ @Test
+ public void test_5_0_UpdatePost_Ok() {
+ Post updatedPost = samplePost("8","Update Post","Updating a post!");
+ when(postService.getPostById(updatedPost.getId())).thenReturn(Optional.of(updatedPost));
+ Response updateResponse = postsApi.updatePost(updatedPost, null);
+ assertEquals(updateResponse.getStatus(),Response.Status.CREATED.getStatusCode());
+ assertEquals((Post)updateResponse.getEntity(), updatedPost);
+ }
+
+ @Test
+ public void test_5_1_UpdatePost_NotFound() {
+ Post updatedPost = samplePost("9","Update Post","Updating a post!");
+ when(postService.getPostById(updatedPost.getId())).thenReturn(Optional.empty());
+ Response updateResponse = postsApi.updatePost(updatedPost, null);
+ assertEquals(updateResponse.getStatus(),Response.Status.NOT_FOUND.getStatusCode());
+ }
+
+ // helper method.
+ private Post samplePost(String id, String title, String content) {
+ Post post = new Post();
+ post.setId(id);
+ post.setTitle(title);
+ post.setContent(content);
+ return post;
+ }
+
+}
diff --git a/integration-test/.gitignore b/integration-test/.gitignore
new file mode 100644
index 0000000..b83d222
--- /dev/null
+++ b/integration-test/.gitignore
@@ -0,0 +1 @@
+/target/
diff --git a/integration-test/pom.xml b/integration-test/pom.xml
index e5d22fa..3308247 100644
--- a/integration-test/pom.xml
+++ b/integration-test/pom.xml
@@ -14,17 +14,22 @@
junit
4.12
-
-
-
diff --git a/integration-test/src/test/java/com/pierceecom/blog/BlogTestIntegr.java b/integration-test/src/test/java/com/pierceecom/blog/BlogTestIntegr.java
index 85e0a71..e353161 100644
--- a/integration-test/src/test/java/com/pierceecom/blog/BlogTestIntegr.java
+++ b/integration-test/src/test/java/com/pierceecom/blog/BlogTestIntegr.java
@@ -1,19 +1,20 @@
package com.pierceecom.blog;
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.io.OutputStream;
-import java.net.HttpURLConnection;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-import static org.junit.Assert.*;
+import static io.restassured.RestAssured.with;
+import static io.restassured.RestAssured.get;
+import static org.hamcrest.Matchers.is;
+
+import java.util.List;
+
+import org.junit.Before;
import org.junit.FixMethodOrder;
import org.junit.Test;
import org.junit.runners.MethodSorters;
+import io.restassured.RestAssured;
+import jakarta.ws.rs.core.MediaType;
+
+
/**
* TODO, Consider it part of the test to replace HttpURLConnection with better
* APIs (for example Jersey-client, JSON-P etc-) to call REST-service
@@ -21,124 +22,126 @@
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class BlogTestIntegr {
- private static final String POST_1 = "{\"id\":\"1\",\"title\":\"First title\",\"content\":\"First content\"}";
- private static final String POST_2 = "{\"id\":\"2\",\"title\":\"Second title\",\"content\":\"Second content\"}";
- private static final String POSTS_URI = "http://localhost:8080/blog-web/posts/";
-
+ private static final String VALID_POST = "{\"id\":\"\",\"title\":\"First title\",\"content\":\"First content\"}";
+ private static final String INVALID_POST = "{\"id\":\"\",\"title\":\"Second title\",\"content\":\"Invalid content🙂\"}";
+ private static final String UPDATE_POST = "{\"id\":\"ID\",\"title\":\"First title\",\"content\":\"Content Updated\"}";
public BlogTestIntegr() {
}
-
- @Test
- public void test_1_BlogWithoutPosts() {
- String output = GET(POSTS_URI, 200);
- assertEquals("[]", output);
+
+ @Before
+ public void setup(){
+ RestAssured.baseURI = "http://localhost:8080/blog-web";
}
-
+
@Test
- public void test_2_AddPosts() {
- String location = POST(POSTS_URI, POST_1);
- assertEquals(POSTS_URI + "1", location);
-
- location = POST(POSTS_URI, POST_2);
- assertEquals(POSTS_URI + "2", location);
- }
-
+ public void test_1_0_GetAllPosts_NoPost() {
+ get("/posts")
+ .then()
+ .assertThat()
+ .body(is("[]"));
+ }
+
@Test
- public void test_3_GetPost() {
- String postJson = GET(POSTS_URI + "1", 200);
- assertEquals(POST_1, postJson);
-
- postJson = GET(POSTS_URI + "2", 200);
- assertEquals(POST_2, postJson);
+ public void test_2_0_AddPost_Ok() {
+ with()
+ .body(VALID_POST)
+ .contentType(MediaType.APPLICATION_JSON)
+ .when()
+ .request("POST", "/posts")
+ .then()
+ .statusCode(201);
+ }
+
+ @Test
+ public void test_2_1_AddPost_InvalidContent() {
+ with()
+ .body(INVALID_POST)
+ .contentType(MediaType.APPLICATION_JSON)
+ .when()
+ .request("POST", "/posts")
+ .then()
+ .statusCode(400);
+ }
+
+ @Test
+ public void test_3_0_GetPost_Ok() {
+ get("/posts/"+getPostId())
+ .then()
+ .statusCode(200);
}
-
+
+ @Test
+ public void test_3_1_GetPost_NoContent() {
+ get("/posts/WrongId")
+ .then()
+ .statusCode(204);
+ }
+
@Test
- public void test_4_GetAllPosts() {
- String output = GET(POSTS_URI, 200);
- assertEquals("[" + POST_1 + "," + POST_2 + "]", output);
+ public void test_4_0_GetAllPosts() {
+ get("/posts")
+ .then()
+ .assertThat()
+ .statusCode(200);
}
@Test
- public void test_5_DeletePosts() {
- DELETE(POSTS_URI + "1", 200);
- // Should now be gone
- GET(POSTS_URI + "1", 204);
-
- DELETE(POSTS_URI + "2", 200);
- // Should now be gone
- GET(POSTS_URI + "2", 204);
-
+ public void test_5_0_UpdatePost_Ok() {
+ String post = UPDATE_POST.replace("ID", getPostId());
+ with()
+ .body(post)
+ .contentType(MediaType.APPLICATION_JSON)
+ .when()
+ .request("PUT", "/posts")
+ .then()
+ .statusCode(201)
+ .assertThat()
+ .body("content", is("Content Updated"));
}
-
+
@Test
- public void test_6_GetAllPostsShouldNowBeEmpty() {
- String output = GET(POSTS_URI, 200);
- assertEquals("[]", output);
+ public void test_5_1_UpdatePost_NotFound() {
+ with()
+ .body(UPDATE_POST)
+ .contentType(MediaType.APPLICATION_JSON)
+ .when()
+ .request("PUT", "/posts")
+ .then()
+ .statusCode(404);
}
-
- /* Helper methods */
- private String GET(String uri, int expectedResponseCode) {
- StringBuilder sb = new StringBuilder();
- try {
- URL url = new URL(uri);
- HttpURLConnection conn = (HttpURLConnection) url.openConnection();
- conn.setRequestMethod("GET");
- conn.setRequestProperty("Accept", "application/json");
- assertEquals(expectedResponseCode, conn.getResponseCode());
- BufferedReader br = new BufferedReader(new InputStreamReader((conn.getInputStream())));
-
- String output;
- while ((output = br.readLine()) != null) {
- sb.append(output);
- }
-
- conn.disconnect();
- } catch (MalformedURLException ex) {
- Logger.getLogger(BlogTestIntegr.class.getName()).log(Level.SEVERE, null, ex);
- } catch (IOException ex) {
- Logger.getLogger(BlogTestIntegr.class.getName()).log(Level.SEVERE, null, ex);
- }
- return sb.toString();
+
+ @Test
+ public void test_6_0_DeletePost_NotFound() {
+ with()
+ .request("DELETE", "/posts/WrongId")
+ .then()
+ .statusCode(404);
}
-
- private String POST(String uri, String json) {
- String location = "";
- try {
- URL url = new URL(uri);
- HttpURLConnection conn = (HttpURLConnection) url.openConnection();
- conn.setDoOutput(true);
- conn.setRequestMethod("POST");
- conn.setRequestProperty("Content-Type", "application/json");
-
- OutputStream os = conn.getOutputStream();
- os.write(json.getBytes());
- os.flush();
- assertEquals(201, conn.getResponseCode());
-
- location = conn.getHeaderField("Location");
- conn.disconnect();
-
- } catch (MalformedURLException ex) {
- Logger.getLogger(BlogTestIntegr.class.getName()).log(Level.SEVERE, null, ex);
- } catch (IOException ex) {
- Logger.getLogger(BlogTestIntegr.class.getName()).log(Level.SEVERE, null, ex);
- }
- return location;
+
+ @Test
+ public void test_6_1_DeletePost_Ok() {
+ with()
+ .request("DELETE", "/posts/"+getPostId())
+ .then()
+ .statusCode(200);
}
-
- private void DELETE(String uri, int expectedResponseCode) {
- try {
- URL url = new URL(uri);
- HttpURLConnection conn = (HttpURLConnection) url.openConnection();
- conn.setRequestMethod("DELETE");
- conn.setRequestProperty("Accept", "application/json");
- assertEquals(expectedResponseCode, conn.getResponseCode());
- } catch (MalformedURLException ex) {
- Logger.getLogger(BlogTestIntegr.class.getName()).log(Level.SEVERE, null, ex);
- } catch (IOException ex) {
- Logger.getLogger(BlogTestIntegr.class.getName()).log(Level.SEVERE, null, ex);
- }
+
+ @Test
+ public void test_7_0_GetAllPostsShouldNowBeEmpty() {
+ get("/posts")
+ .then()
+ .assertThat()
+ .body(is("[]"));
+ }
+
+ // Helper method.
+ private String getPostId() {
+ List postIds = get("/posts")
+ .getBody()
+ .jsonPath()
+ .getList("id");
+ return postIds.get(0);
}
}