From c8d1c555000b34d2bdd97b4ae385405b36311dd3 Mon Sep 17 00:00:00 2001
From: Kai Moritz <kai@juplo.de>
Date: Wed, 30 Sep 2020 08:42:38 +0200
Subject: [PATCH] Refined the test: @ParameterizedTest adds no additional
 insight here

* The parameterized tests only test the difference between an empty and an
  non-empty Optional.
* The actual number is meaningless, because the business logic is mocked
  away anyway!
* Hence, the parameterized version only tests the correctness of our mocking:
  The test could only fail, if we make a mistake in the setup of the
  expectations, not in the code under test!
* Also splitted up some test-cases more logically.
---
 .../java/de/juplo/demo/ExampleController.java |  6 +-
 .../ExceptionHandlingApplicationTests.java    | 69 ++++++++++++-------
 2 files changed, 48 insertions(+), 27 deletions(-)

diff --git a/src/main/java/de/juplo/demo/ExampleController.java b/src/main/java/de/juplo/demo/ExampleController.java
index d919b63..de806ef 100644
--- a/src/main/java/de/juplo/demo/ExampleController.java
+++ b/src/main/java/de/juplo/demo/ExampleController.java
@@ -5,10 +5,8 @@ import org.slf4j.LoggerFactory;
 import org.springframework.http.HttpStatus;
 import org.springframework.stereotype.Controller;
 import org.springframework.ui.Model;
-import org.springframework.web.bind.annotation.ExceptionHandler;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestParam;
-import org.springframework.web.bind.annotation.ResponseStatus;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.servlet.DispatcherServlet;
 import org.thymeleaf.exceptions.TemplateProcessingException;
 
 import java.util.Optional;
diff --git a/src/test/java/de/juplo/demo/ExceptionHandlingApplicationTests.java b/src/test/java/de/juplo/demo/ExceptionHandlingApplicationTests.java
index a80ffd3..65d3e4a 100644
--- a/src/test/java/de/juplo/demo/ExceptionHandlingApplicationTests.java
+++ b/src/test/java/de/juplo/demo/ExceptionHandlingApplicationTests.java
@@ -1,8 +1,6 @@
 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.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -13,9 +11,7 @@ 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.ArgumentMatchers.anyInt;
 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;
@@ -45,24 +41,49 @@ class ExceptionHandlingApplicationTests {
 		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());
+	@Test
+	void test200ForEmptyAnswer() throws Exception {
+		mvc
+				.perform(get(URI.create("http://FOO/?answer=")))
+				.andExpect(status().isOk());
+
+		verify(service, times(0)).checkAnswer(anyInt());
+	}
+
+	@Test
+	void test200ForAnswerThatContainsOnlyWhitespace() throws Exception {
+		mvc
+				.perform(get(URI.create("http://FOO/?answer=%20")))
+				.andExpect(status().isOk());
+
+		verify(service, times(0)).checkAnswer(anyInt());
+	}
+
+	@Test
+	void test200ForWrongAnswer() throws Exception {
+		when(service.checkAnswer(anyInt())).thenReturn(Optional.of(false));
+
+		mvc
+				.perform(get(URI.create("http://FOO/?answer=1234")))
+				.andExpect(status().isOk());
+
+		verify(service, times(1)).checkAnswer(anyInt());
+	}
+
+	@Test
+	void test200ForCorrectAnswer() throws Exception {
+		when(service.checkAnswer(anyInt())).thenReturn(Optional.of(true));
 
 		mvc
-				.perform(get(URI.create("http://FOO/?answer=" + number)))
+				.perform(get(URI.create("http://FOO/?answer=1234")))
 				.andExpect(status().isOk());
+
+		verify(service, times(1)).checkAnswer(anyInt());
 	}
 
-	@ParameterizedTest
-	@ValueSource(ints = { -1, -2, Integer.MIN_VALUE })
-	void test400ForNegativeAnswer_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());
+	@Test
+	void test400ForNegativeAnswer_NOT_WORKING() throws Exception {
+		when(service.checkAnswer(anyInt())).thenReturn(Optional.empty());
 
 		// The expected behaviour of the following test is, that the NoSuchElementException
 		// with the message "No value present", that is raised, when the view calls .get()
@@ -72,18 +93,20 @@ 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/?answer=" + number)))
-				.andExpect(status().isInternalServerError());
+				.perform(get(URI.create("http://FOO/?answer=1234")))
+				.andExpect(status().isBadRequest());
+
+		verify(service, times(1)).checkAnswer(anyInt());
 	}
 
 	@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());
+		when(service.checkAnswer(anyInt())).thenReturn(Optional.empty());
 
 		mvc
 				.perform(get(URI.create("http://FOO/?answer=bar")))
 				.andExpect(status().isBadRequest());
+
+		verify(service, times(0)).checkAnswer(anyInt());
 	}
 }
-- 
2.20.1