From: Kai Moritz Date: Sun, 27 Sep 2020 09:23:03 +0000 (+0200) Subject: Further refined the example X-Git-Url: http://juplo.de/gitweb/?a=commitdiff_plain;h=ee41a8be1e0c808cd74ff5118054adf98af447c8;p=demos%2Ftesting Further refined the example * Introduced an ExampleService * The service checks the answer for The Ultimate Question Of Life, The Universe And Everything * Requests without any answer are tolarated, so that the page with the question can be rendered * Only numbers (Integer) are allowed as answer. * Negative numbers are not allowed as answers: the service answers with an empty Optional. * The view contains a bug, that results in a 503 for negative answers. --- diff --git a/src/main/java/de/juplo/demo/ExampleController.java b/src/main/java/de/juplo/demo/ExampleController.java index b6e75d8..e16b147 100644 --- a/src/main/java/de/juplo/demo/ExampleController.java +++ b/src/main/java/de/juplo/demo/ExampleController.java @@ -11,6 +11,8 @@ import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseStatus; import org.thymeleaf.exceptions.TemplateInputException; +import java.util.Optional; + @Controller public class ExampleController { @@ -18,14 +20,27 @@ public class ExampleController LoggerFactory.getLogger(ExampleController.class); + private final ExampleService service; + + + public ExampleController(ExampleService service) + { + this.service = service; + } + + @RequestMapping("/") public String controller( - @RequestParam(defaultValue = "a") String template, + @RequestParam(required = false) Integer answer, Model model ) { - model.addAttribute("template", template); - return template; + Optional outcome = + answer == null ? null : service.checkAnswer(answer); + + model.addAttribute("answer", answer); + model.addAttribute("outcome", outcome); + return "view"; } @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) diff --git a/src/main/java/de/juplo/demo/ExampleService.java b/src/main/java/de/juplo/demo/ExampleService.java new file mode 100644 index 0000000..375e8f7 --- /dev/null +++ b/src/main/java/de/juplo/demo/ExampleService.java @@ -0,0 +1,21 @@ +package de.juplo.demo; + +import org.springframework.lang.Nullable; +import org.springframework.stereotype.Component; + +import java.util.Optional; + +@Component +public class ExampleService +{ + public Optional checkAnswer(int answer) + { + if (answer < 0) + return Optional.empty(); + + if (answer == 42) + return Optional.of(true); + else + return Optional.of(false); + } +} diff --git a/src/main/resources/templates/a.html b/src/main/resources/templates/a.html deleted file mode 100644 index 60de028..0000000 --- a/src/main/resources/templates/a.html +++ /dev/null @@ -1,28 +0,0 @@ - - - - Testing Exception-Handling - Template A - - - -

Template A

-
-

TEXT

-

- Type in a or b - for an existing template (no exception). Type in any other string for a - non-existent template: Thymeleaf will throw a - TemplateInputException! -

-
-
-
-
- - -
- -
-
- - diff --git a/src/main/resources/templates/b.html b/src/main/resources/templates/b.html deleted file mode 100644 index c89c69f..0000000 --- a/src/main/resources/templates/b.html +++ /dev/null @@ -1,28 +0,0 @@ - - - - Testing Exception-Handling - Template B - - - -

Template B

-
-

TEXT

-

- Type in a or b - for an existing template (no exception). Type in any other string for a - non-existent template: Thymeleaf will throw a - TemplateInputException! -

-
-
-
-
- - -
- -
-
- - diff --git a/src/main/resources/templates/view.html b/src/main/resources/templates/view.html new file mode 100644 index 0000000..47fdca4 --- /dev/null +++ b/src/main/resources/templates/view.html @@ -0,0 +1,28 @@ + + + + Template: view + + + +

Deeep Thought

+
+

+ What is the answer to the ultimate question of life, the universe and everything? +

+
    +
  • Presented answer: ANSWER
  • +
  • Outcome: OUTCOME
  • +
+
+
+
+
+ + + +
+
+
+ + diff --git a/src/test/java/de/juplo/demo/ExceptionHandlingApplicationTests.java b/src/test/java/de/juplo/demo/ExceptionHandlingApplicationTests.java index 9e6d753..5d3ca21 100644 --- a/src/test/java/de/juplo/demo/ExceptionHandlingApplicationTests.java +++ b/src/test/java/de/juplo/demo/ExceptionHandlingApplicationTests.java @@ -1,14 +1,23 @@ package de.juplo.demo; import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; +import org.mockito.Mockito; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.test.web.servlet.MockMvc; import java.net.URI; +import java.util.Optional; +import static org.mockito.AdditionalMatchers.geq; +import static org.mockito.AdditionalMatchers.lt; +import static org.mockito.ArgumentMatchers.*; +import static org.mockito.Mockito.*; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -17,6 +26,9 @@ class ExceptionHandlingApplicationTests { private final static Logger LOG = LoggerFactory.getLogger(ExceptionHandlingApplicationTests.class); + @MockBean + ExampleService service; + @Autowired MockMvc mvc; @@ -26,17 +38,33 @@ class ExceptionHandlingApplicationTests { } @Test - void test200() throws Exception { + void test200ForNoAnswer() throws Exception { mvc - .perform(get(URI.create("http://FOO/?template=a"))) + .perform(get(URI.create("http://FOO/"))) .andExpect(status().isOk()); + + verify(service, times(0)).checkAnswer(anyInt()); + } + + @ParameterizedTest + @ValueSource(ints = { 0, 1, 2, 3, 4, 5, 41, 42, 43, 666, Integer.MAX_VALUE }) + void test200ForPositiveAnswer(int number) throws Exception { + when(service.checkAnswer(eq(42))).thenReturn(Optional.of(true)); + when(service.checkAnswer(geq(0))).thenReturn(Optional.of(false)); + when(service.checkAnswer(lt(0))).thenReturn(Optional.empty()); + mvc - .perform(get(URI.create("http://FOO/?template=b"))) + .perform(get(URI.create("http://FOO/?answer=" + number))) .andExpect(status().isOk()); } - @Test - void test503_NOT_WORKING() throws Exception { + @ParameterizedTest + @ValueSource(ints = { -1, -2, Integer.MIN_VALUE }) + void test500ForNegativeAnswer_NOT_WORKING(int number) throws Exception { + when(service.checkAnswer(eq(42))).thenReturn(Optional.of(true)); + when(service.checkAnswer(geq(0))).thenReturn(Optional.of(false)); + when(service.checkAnswer(lt(0))).thenReturn(Optional.empty()); + // The expected behaviour of the following test is, that the // TemplateInputException, that is thrown by Thymeleaf because of the non-existent // template-resource, is catched and reported as 503 Internal Server Error, as it @@ -45,7 +73,18 @@ class ExceptionHandlingApplicationTests { // Instead, the exception bubbles up, becomes wrapped in a NestedServletException // and is thrown in the call to perform()! mvc - .perform(get(URI.create("http://FOO/?template=foo"))) + .perform(get(URI.create("http://FOO/?answer=" + number))) .andExpect(status().isInternalServerError()); } + + @Test + void test400ForStringInput() throws Exception { + when(service.checkAnswer(eq(42))).thenReturn(Optional.of(true)); + when(service.checkAnswer(geq(0))).thenReturn(Optional.of(false)); + when(service.checkAnswer(lt(0))).thenReturn(Optional.empty()); + + mvc + .perform(get(URI.create("http://FOO/?answer=bar"))) + .andExpect(status().isBadRequest()); + } }