From 9e597dc1d4e27808a54dd1a70001d8018431fdaa Mon Sep 17 00:00:00 2001 From: Ralf Ueberfuhr Date: Mon, 18 Dec 2023 16:01:09 +0100 Subject: [PATCH] add POST /blogposts --- http-requests/GET-blogposts.http | 2 +- http-requests/POST-blogposts.http | 14 ++++++ .../spring/blog/BlogPostController.java | 28 ++++++++--- .../schulung/spring/blog/BlogPostDto.java | 19 ++++++++ .../spring/blog/BlogPostApiTests.java | 47 ++++++++++++++++++- 5 files changed, 100 insertions(+), 10 deletions(-) create mode 100644 http-requests/POST-blogposts.http create mode 100644 src/main/java/de/sample/schulung/spring/blog/BlogPostDto.java diff --git a/http-requests/GET-blogposts.http b/http-requests/GET-blogposts.http index c9cc021..eb663cb 100644 --- a/http-requests/GET-blogposts.http +++ b/http-requests/GET-blogposts.http @@ -10,7 +10,7 @@ Accept: application/json ### GET http://localhost:9080/blogposts -Accept: text/plain +Accept: application/xml > {% client.test("BlogPosts returned", () => { diff --git a/http-requests/POST-blogposts.http b/http-requests/POST-blogposts.http new file mode 100644 index 0000000..73eae01 --- /dev/null +++ b/http-requests/POST-blogposts.http @@ -0,0 +1,14 @@ +POST http://localhost:9080/blogposts +Accept: application/json +Content-Type: application/json + +{ + "title": "test", + "content": "Das ist ein Test" +} + +> {% + client.test("BlogPosts returned", () => { + client.assert(response.status === 201); + }); +%} diff --git a/src/main/java/de/sample/schulung/spring/blog/BlogPostController.java b/src/main/java/de/sample/schulung/spring/blog/BlogPostController.java index a4714b6..5cc396e 100644 --- a/src/main/java/de/sample/schulung/spring/blog/BlogPostController.java +++ b/src/main/java/de/sample/schulung/spring/blog/BlogPostController.java @@ -1,18 +1,32 @@ package de.sample.schulung.spring.blog; -import org.springframework.stereotype.Controller; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.web.bind.annotation.*; -@Controller +import java.time.LocalDateTime; +import java.util.UUID; + +@RestController @RequestMapping("/blogposts") public class BlogPostController { - @GetMapping - @ResponseBody + @GetMapping( + produces = MediaType.APPLICATION_JSON_VALUE + ) String sayHello() { return "Hello World"; } + @PostMapping( + consumes = MediaType.APPLICATION_JSON_VALUE, + produces = MediaType.APPLICATION_JSON_VALUE + ) + @ResponseStatus(HttpStatus.CREATED) + BlogPostDto createBlogPost(@RequestBody BlogPostDto blogPostDto) { + blogPostDto.setId(UUID.randomUUID()); + blogPostDto.setTimestamp(LocalDateTime.now()); + return blogPostDto; + } + } diff --git a/src/main/java/de/sample/schulung/spring/blog/BlogPostDto.java b/src/main/java/de/sample/schulung/spring/blog/BlogPostDto.java new file mode 100644 index 0000000..1ddb854 --- /dev/null +++ b/src/main/java/de/sample/schulung/spring/blog/BlogPostDto.java @@ -0,0 +1,19 @@ +package de.sample.schulung.spring.blog; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; + +import java.time.LocalDateTime; +import java.util.UUID; + +@Data +public class BlogPostDto { + + @JsonProperty(access = JsonProperty.Access.READ_ONLY) + private UUID id; + private String title; + private String content; + @JsonProperty(access = JsonProperty.Access.READ_ONLY) + private LocalDateTime timestamp; + +} diff --git a/src/test/java/de/sample/schulung/spring/blog/BlogPostApiTests.java b/src/test/java/de/sample/schulung/spring/blog/BlogPostApiTests.java index 9d43096..9913685 100644 --- a/src/test/java/de/sample/schulung/spring/blog/BlogPostApiTests.java +++ b/src/test/java/de/sample/schulung/spring/blog/BlogPostApiTests.java @@ -7,7 +7,8 @@ import org.springframework.http.MediaType; import org.springframework.test.web.servlet.MockMvc; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @SpringBootTest @@ -23,9 +24,51 @@ void shouldReturn200WhenGetBlogPosts() throws Exception { get("/blogposts") .accept(MediaType.APPLICATION_JSON) ) + .andExpect(status().isOk()) + .andExpect(content().contentType(MediaType.APPLICATION_JSON)); + } + + /* + * Testfall: + * - Lege BlogPost an (title: "test") + * - Frage BlogPost ab und prüfe, ob Titel == "test" + */ + + @Test + void shouldReturn406WhenGetBlogPostsWithInvalidMediaType() throws Exception { + mvc.perform( + get("/blogposts") + .accept(MediaType.APPLICATION_XML) + ) .andExpect( - status().isOk() + status().isNotAcceptable() ); } + // TODO wenn zu komplex -> @Nested + + @Test + void shouldCreateBlogPostSuccessfully() throws Exception { + mvc.perform( + post("/blogposts") + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + .content(""" + { + "title": "test", + "content": "Das ist ein Test" + } + """) + + ) + .andExpect(status().isCreated()) + .andExpect(jsonPath("$.title").value("test")) + .andExpect(jsonPath("$.id").exists()) + .andExpect(jsonPath("$.timestamp").exists()); + // .title = "test" + // Location-Header + } + + // TODO wenn ID im Request mitgeschickt wird -> ?? + }