Browse Source

Fix tests up a bit and add documemtation

See gh-18
Dave Syer 10 years ago
parent
commit
489d7ae669

+ 38
- 0
README.adoc View File

136
 Greetings from Spring Boot!
136
 Greetings from Spring Boot!
137
 ....
137
 ....
138
 
138
 
139
+== Add Unit Tests
140
+
141
+You will want to add a test for the endpoint you added, and Spring Test already provides some machinery for that, and it's easy to include in your project.
142
+
143
+Add this to your build file's list of dependencies:
144
+
145
+[source,groovy]
146
+----
147
+include::complete/build.gradle[tag=tests]
148
+----
149
+
150
+If you are using Maven, add this to your list of dependencies:
151
+
152
+[source,xml]
153
+----
154
+include::complete/pom.xml[tag=tests]
155
+----
156
+
157
+Now write a simple unit test that mocks the servlet request and response through your endpoint:
158
+
159
+`src/test/java/hello/HelloControllerTest.java`
160
+[source,java]
161
+----
162
+include::initial/src/test/java/hello/HelloControllerTest.java[]
163
+----
164
+
165
+Note the use of the `MockServletContext` to set up an empty `WebApplicationContext` so the `HelloController` can be created in the `@Before` and passed to `MockMvcBuilders.standaloneSetup()`. An alternative would be to create the full application context using the `Application` class and `@Autowired` the `HelloController` into the test. The `MockMvc` comes from Spring Test and allows you, via a set of convenient builder classes, to send HTTP requests into the `DispatcherServlet` and make assertions about the result.
166
+
167
+As well as mocking the HTTP request cycle we can also use Spring Boot to write a very simple full-stack integration test. For example, instead of (or as well as) the mock test above we could do this:
168
+
169
+`src/test/java/hello/HelloControllerTest.java`
170
+[source,java]
171
+----
172
+include::initial/src/test/java/hello/HelloControllerIT.java[]
173
+----
174
+
175
+The embedded server is started up on a random port by virtue of the `@IntegrationTest("${server.port=0}")` and the actual port is discovered at runtime with the `@Value("${local.server.port}")`.
176
+
139
 == Add production-grade services
177
 == Add production-grade services
140
 If you are building a web site for your business, you probably need to add some management services. Spring Boot provides several out of the box with its http://docs.spring.io/spring-boot/docs/{spring_boot_version}/reference/htmlsingle/#production-ready[actuator module], such as health, audits, beans, and more.
178
 If you are building a web site for your business, you probably need to add some management services. Spring Boot provides several out of the box with its http://docs.spring.io/spring-boot/docs/{spring_boot_version}/reference/htmlsingle/#production-ready[actuator module], such as health, audits, beans, and more.
141
 
179
 

+ 2
- 0
complete/build.gradle View File

26
     // tag::actuator[]
26
     // tag::actuator[]
27
     compile("org.springframework.boot:spring-boot-starter-actuator")
27
     compile("org.springframework.boot:spring-boot-starter-actuator")
28
     // end::actuator[]
28
     // end::actuator[]
29
+    // tag::tests[]
29
     testCompile("org.springframework.boot:spring-boot-starter-test")
30
     testCompile("org.springframework.boot:spring-boot-starter-test")
31
+    // end::tests[]
30
 }
32
 }
31
 
33
 
32
 task wrapper(type: Wrapper) {
34
 task wrapper(type: Wrapper) {

+ 2
- 0
complete/pom.xml View File

24
             <artifactId>spring-boot-starter-actuator</artifactId>
24
             <artifactId>spring-boot-starter-actuator</artifactId>
25
         </dependency>
25
         </dependency>
26
         <!-- end::actuator[] -->
26
         <!-- end::actuator[] -->
27
+        <!-- tag::tests[] -->
27
         <dependency>
28
         <dependency>
28
             <groupId>org.springframework.boot</groupId>
29
             <groupId>org.springframework.boot</groupId>
29
             <artifactId>spring-boot-starter-test</artifactId>
30
             <artifactId>spring-boot-starter-test</artifactId>
30
             <scope>test</scope>
31
             <scope>test</scope>
31
         </dependency>
32
         </dependency>
33
+        <!-- end::tests[] -->
32
     </dependencies>
34
     </dependencies>
33
 
35
 
34
     <properties>
36
     <properties>

+ 1
- 1
complete/src/main/java/hello/HelloController.java View File

6
 @RestController
6
 @RestController
7
 public class HelloController {
7
 public class HelloController {
8
     
8
     
9
-    @RequestMapping("/hello")
9
+    @RequestMapping("/")
10
     public String index() {
10
     public String index() {
11
         return "Greetings from Spring Boot!";
11
         return "Greetings from Spring Boot!";
12
     }
12
     }

+ 12
- 7
complete/src/test/java/hello/HelloControllerIT.java View File

1
 package hello;
1
 package hello;
2
 
2
 
3
+import static org.hamcrest.Matchers.is;
4
+import static org.junit.Assert.assertThat;
5
+
6
+import java.net.URL;
7
+
3
 import org.junit.Before;
8
 import org.junit.Before;
4
 import org.junit.Test;
9
 import org.junit.Test;
5
 import org.junit.runner.RunWith;
10
 import org.junit.runner.RunWith;
11
+import org.springframework.beans.factory.annotation.Value;
6
 import org.springframework.boot.test.IntegrationTest;
12
 import org.springframework.boot.test.IntegrationTest;
7
 import org.springframework.boot.test.SpringApplicationConfiguration;
13
 import org.springframework.boot.test.SpringApplicationConfiguration;
8
 import org.springframework.boot.test.TestRestTemplate;
14
 import org.springframework.boot.test.TestRestTemplate;
11
 import org.springframework.test.context.web.WebAppConfiguration;
17
 import org.springframework.test.context.web.WebAppConfiguration;
12
 import org.springframework.web.client.RestTemplate;
18
 import org.springframework.web.client.RestTemplate;
13
 
19
 
14
-import java.net.URL;
15
-
16
-import static org.hamcrest.Matchers.is;
17
-import static org.junit.Assert.assertThat;
18
-
19
 @RunWith(SpringJUnit4ClassRunner.class)
20
 @RunWith(SpringJUnit4ClassRunner.class)
20
 @SpringApplicationConfiguration(classes = Application.class)
21
 @SpringApplicationConfiguration(classes = Application.class)
21
 @WebAppConfiguration
22
 @WebAppConfiguration
22
-@IntegrationTest({"server.port=9090"})
23
+@IntegrationTest({"server.port=0"})
23
 public class HelloControllerIT {
24
 public class HelloControllerIT {
25
+
26
+    @Value("${local.server.port}")
27
+    private int port;
28
+
24
 	private URL base;
29
 	private URL base;
25
 	private RestTemplate template;
30
 	private RestTemplate template;
26
 
31
 
27
 	@Before
32
 	@Before
28
 	public void setUp() throws Exception {
33
 	public void setUp() throws Exception {
29
-		this.base = new URL("http://localhost:9090/hello");
34
+		this.base = new URL("http://localhost:" + port + "/");
30
 		template = new TestRestTemplate();
35
 		template = new TestRestTemplate();
31
 	}
36
 	}
32
 
37
 

+ 7
- 8
complete/src/test/java/hello/HelloControllerTest.java View File

1
 package hello;
1
 package hello;
2
 
2
 
3
+import static org.hamcrest.Matchers.is;
4
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
5
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
6
+
3
 import org.junit.Before;
7
 import org.junit.Before;
4
 import org.junit.Test;
8
 import org.junit.Test;
5
 import org.junit.runner.RunWith;
9
 import org.junit.runner.RunWith;
6
 import org.springframework.boot.test.SpringApplicationConfiguration;
10
 import org.springframework.boot.test.SpringApplicationConfiguration;
7
 import org.springframework.http.MediaType;
11
 import org.springframework.http.MediaType;
8
 import org.springframework.mock.web.MockServletContext;
12
 import org.springframework.mock.web.MockServletContext;
9
-import org.springframework.test.context.ContextConfiguration;
10
 import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
13
 import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
11
 import org.springframework.test.context.web.WebAppConfiguration;
14
 import org.springframework.test.context.web.WebAppConfiguration;
12
 import org.springframework.test.web.servlet.MockMvc;
15
 import org.springframework.test.web.servlet.MockMvc;
13
 import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
16
 import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
14
 import org.springframework.test.web.servlet.setup.MockMvcBuilders;
17
 import org.springframework.test.web.servlet.setup.MockMvcBuilders;
15
 
18
 
16
-import static org.hamcrest.Matchers.is;
17
-import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
18
-import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
19
-
20
 @RunWith(SpringJUnit4ClassRunner.class)
19
 @RunWith(SpringJUnit4ClassRunner.class)
21
-@SpringApplicationConfiguration(classes = Application.class)
22
-@ContextConfiguration(classes = MockServletContext.class)
20
+@SpringApplicationConfiguration(classes = MockServletContext.class)
23
 @WebAppConfiguration
21
 @WebAppConfiguration
24
 public class HelloControllerTest {
22
 public class HelloControllerTest {
23
+
25
 	private MockMvc mvc;
24
 	private MockMvc mvc;
26
 
25
 
27
 	@Before
26
 	@Before
31
 
30
 
32
 	@Test
31
 	@Test
33
 	public void getHello() throws Exception {
32
 	public void getHello() throws Exception {
34
-		mvc.perform(MockMvcRequestBuilders.get("/hello").accept(MediaType.APPLICATION_JSON))
33
+		mvc.perform(MockMvcRequestBuilders.get("/").accept(MediaType.APPLICATION_JSON))
35
 				.andExpect(status().isOk())
34
 				.andExpect(status().isOk())
36
 				.andExpect(content().string(is("Greetings from Spring Boot!")));
35
 				.andExpect(content().string(is("Greetings from Spring Boot!")));
37
 	}
36
 	}

+ 0
- 18
initial/pom.xml View File

14
     </parent>
14
     </parent>
15
 
15
 
16
     <dependencies>
16
     <dependencies>
17
-	    <!-- tag::jetty[] -->
18
         <dependency>
17
         <dependency>
19
             <groupId>org.springframework.boot</groupId>
18
             <groupId>org.springframework.boot</groupId>
20
             <artifactId>spring-boot-starter-web</artifactId>
19
             <artifactId>spring-boot-starter-web</artifactId>
21
-            <exclusions>
22
-                <exclusion>
23
-                    <groupId>org.springframework.boot</groupId>
24
-                    <artifactId>spring-boot-starter-tomcat</artifactId>
25
-                </exclusion>
26
-	    </exclusions>
27
         </dependency>
20
         </dependency>
28
-        <dependency>
29
-            <groupId>org.springframework.boot</groupId>
30
-            <artifactId>spring-boot-starter-jetty</artifactId>
31
-        </dependency>
32
-        <!-- end::jetty[] -->
33
-        <!-- tag::actuator[] -->
34
-        <dependency>
35
-            <groupId>org.springframework.boot</groupId>
36
-            <artifactId>spring-boot-starter-actuator</artifactId>
37
-        </dependency>
38
-        <!-- end::actuator[] -->
39
     </dependencies>
21
     </dependencies>
40
 
22
 
41
     <properties>
23
     <properties>