Skip to content

Commit 5de6bb8

Browse files
authored
Merge pull request JeffLi1993#76 from strongant/master
完善章节4单元测试
2 parents 6473f89 + b107d49 commit 5de6bb8

File tree

11 files changed

+335
-7
lines changed

11 files changed

+335
-7
lines changed

chapter-4-spring-boot-validating-form-input/pom.xml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,6 @@
5454
<dependency>
5555
<groupId>com.h2database</groupId>
5656
<artifactId>h2</artifactId>
57-
<scope>runtime</scope>
5857
</dependency>
5958

6059
<!-- 模板引擎 Thymeleaf 依赖 -->
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,40 @@
11
package spring.boot.core;
22

3+
import org.slf4j.Logger;
4+
import org.slf4j.LoggerFactory;
5+
import org.springframework.beans.factory.annotation.Autowired;
6+
import org.springframework.boot.CommandLineRunner;
37
import org.springframework.boot.SpringApplication;
48
import org.springframework.boot.autoconfigure.SpringBootApplication;
9+
import spring.boot.core.domain.User;
10+
import spring.boot.core.domain.UserRepository;
511

612
@SpringBootApplication
7-
public class ValidatingFormInputApplication {
13+
public class ValidatingFormInputApplication implements CommandLineRunner {
814

9-
public static void main(String[] args) {
10-
SpringApplication.run(ValidatingFormInputApplication.class, args);
11-
}
15+
16+
private Logger LOG = LoggerFactory.getLogger(ValidatingFormInputApplication.class);
17+
18+
@Autowired
19+
private UserRepository userRepository;
20+
21+
public static void main(String[] args) {
22+
SpringApplication.run(ValidatingFormInputApplication.class, args);
23+
}
24+
25+
@Override
26+
public void run(String... args) throws Exception {
27+
User user1 = new User("Sergey", 24, "1994-01-01");
28+
User user2 = new User("Ivan", 26, "1994-01-01");
29+
User user3 = new User("Adam", 31, "1994-01-01");
30+
LOG.info("Inserting data in DB.");
31+
userRepository.save(user1);
32+
userRepository.save(user2);
33+
userRepository.save(user3);
34+
LOG.info("User count in DB: {}", userRepository.count());
35+
LOG.info("User with ID 1: {}", userRepository.findById(1L));
36+
LOG.info("Deleting user with ID 2L form DB.");
37+
userRepository.deleteById(2L);
38+
LOG.info("User count in DB: {}", userRepository.count());
39+
}
1240
}

chapter-4-spring-boot-validating-form-input/src/main/java/spring/boot/core/domain/User.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,15 @@ public void setBirthday(String birthday) {
7979
this.birthday = birthday;
8080
}
8181

82+
83+
public User(String name, Integer age, String birthday) {
84+
this.name = name;
85+
this.age = age;
86+
this.birthday = birthday;
87+
}
88+
89+
public User() {}
90+
8291
@Override
8392
public String toString() {
8493
return "User{" +

chapter-4-spring-boot-validating-form-input/src/main/java/spring/boot/core/web/UserController.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ public String putUser(ModelMap map,
103103
/**
104104
* 处理 "/users/{id}" 的 GET 请求,用来删除 User 信息
105105
*/
106-
@RequestMapping(value = "/delete/{id}", method = RequestMethod.GET)
106+
@RequestMapping(value = "/delete/{id}", method = RequestMethod.DELETE)
107107
public String deleteUser(@PathVariable Long id) {
108108

109109
userService.delete(id);
Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,15 @@
1+
## 开启 H2 数据库
2+
spring.h2.console.enabled=true
3+
4+
## 配置 H2 数据库连接信息
5+
spring.datasource.url=jdbc:h2:mem:testdb
6+
spring.datasource.driverClassName=org.h2.Driver
7+
spring.datasource.username=sa
8+
spring.datasource.password=
9+
10+
11+
112
## 是否显示 SQL 语句
2-
spring.jpa.show-sql=true
13+
spring.jpa.show-sql=true
14+
hibernate.dialect=org.hibernate.dialect.H2Dialect
15+
hibernate.hbm2ddl.auto=create
Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
package spring.boot.core.web;
2+
3+
import com.fasterxml.jackson.annotation.JsonInclude;
4+
import com.fasterxml.jackson.core.type.TypeReference;
5+
import com.fasterxml.jackson.databind.ObjectMapper;
6+
import org.junit.Test;
7+
import org.junit.runner.RunWith;
8+
import org.springframework.beans.factory.annotation.Autowired;
9+
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
10+
import org.springframework.boot.test.context.SpringBootTest;
11+
import org.springframework.mock.web.MockHttpServletResponse;
12+
import org.springframework.test.context.TestPropertySource;
13+
import org.springframework.test.context.junit4.SpringRunner;
14+
import org.springframework.test.web.servlet.MockMvc;
15+
import org.springframework.test.web.servlet.MvcResult;
16+
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
17+
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
18+
import org.springframework.util.LinkedMultiValueMap;
19+
import org.springframework.util.MultiValueMap;
20+
import spring.boot.core.ValidatingFormInputApplication;
21+
import spring.boot.core.domain.User;
22+
import spring.boot.core.service.UserService;
23+
24+
import javax.servlet.http.HttpServletResponse;
25+
import java.io.IOException;
26+
import java.util.Collection;
27+
import java.util.Map;
28+
29+
import static junit.framework.TestCase.assertNotNull;
30+
import static junit.framework.TestCase.assertTrue;
31+
import static org.assertj.core.api.Assertions.assertThat;
32+
import static org.hamcrest.CoreMatchers.is;
33+
import static org.hamcrest.beans.HasPropertyWithValue.hasProperty;
34+
import static org.junit.Assert.assertEquals;
35+
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
36+
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
37+
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
38+
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
39+
40+
@RunWith(SpringRunner.class)
41+
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = ValidatingFormInputApplication.class)
42+
@AutoConfigureMockMvc
43+
@TestPropertySource(locations = "classpath:application.properties")
44+
public class UserControllerTest {
45+
46+
47+
@Autowired
48+
private MockMvc mockMvc;
49+
50+
@Autowired
51+
private UserService userService;
52+
53+
@Autowired
54+
private ObjectMapper objectMapper;
55+
56+
@Test
57+
public void getUserList() throws Exception {
58+
mockMvc.perform(get("/users"))
59+
.andExpect(view().name("userList"))
60+
.andExpect(status().isOk())
61+
.andDo(print());
62+
}
63+
64+
private User createUser() {
65+
User user = new User();
66+
user.setName("测试用户");
67+
user.setAge(100);
68+
user.setBirthday("1994-01-01");
69+
return userService.insertByUser(user);
70+
}
71+
72+
@Test
73+
public void createUserForm() throws Exception {
74+
75+
mockMvc.perform(get("/users/create"))
76+
.andDo(print())
77+
.andExpect(view().name("userForm"))
78+
.andExpect(request().attribute("action", "create"))
79+
.andDo(print())
80+
.andReturn();
81+
}
82+
83+
@Test
84+
public void postUser() throws Exception {
85+
User user = createUser();
86+
assertNotNull(user);
87+
88+
MultiValueMap parameters = new LinkedMultiValueMap<String, String>();
89+
Map<String, String> maps = objectMapper.convertValue(user, new TypeReference<Map<String, String>>() {
90+
});
91+
parameters.setAll(maps);
92+
93+
mockMvc.perform(post("/users/create").params(parameters))
94+
.andDo(print())
95+
.andExpect(status().is(HttpServletResponse.SC_FOUND))
96+
.andDo(print())
97+
.andExpect(view().name("redirect:/users/"))
98+
.andDo(print())
99+
.andReturn();
100+
}
101+
102+
@Test
103+
public void getUser() throws Exception {
104+
105+
MvcResult result= mockMvc.perform(get("/users/update/{id}/", 1))
106+
.andExpect(status().isOk())
107+
.andExpect(view().name("userForm"))
108+
.andExpect(MockMvcResultMatchers.model().attributeExists("action"))
109+
.andExpect(model().attribute("user", hasProperty("id", is(1L))))
110+
.andExpect(model().attribute("user", hasProperty("name", is("Sergey"))))
111+
.andExpect(model().attribute("user", hasProperty("age", is(24))))
112+
.andExpect(model().attribute("user", hasProperty("birthday", is("1994-01-01"))))
113+
.andReturn();
114+
115+
116+
MockHttpServletResponse mockResponse=result.getResponse();
117+
assertThat(mockResponse.getContentType()).isEqualTo("text/html;charset=UTF-8");
118+
119+
Collection<String> responseHeaders = mockResponse.getHeaderNames();
120+
assertNotNull(responseHeaders);
121+
assertEquals(2, responseHeaders.size());
122+
assertEquals("Check for Content-Type header", "Accept-Language", responseHeaders.iterator().next());
123+
String responseAsString=mockResponse.getContentAsString();
124+
assertTrue(responseAsString.contains("用户管理"));
125+
}
126+
127+
@Test
128+
public void putUser() throws Exception {
129+
User user = createUser();
130+
assertNotNull(user);
131+
132+
MultiValueMap parameters = new LinkedMultiValueMap<String, String>();
133+
Map<String, String> maps = objectMapper.convertValue(user, new TypeReference<Map<String, String>>() {
134+
});
135+
parameters.setAll(maps);
136+
137+
mockMvc.perform(post("/users/update").params(parameters))
138+
.andDo(print())
139+
.andExpect(status().is(HttpServletResponse.SC_FOUND))
140+
.andDo(print())
141+
.andExpect(view().name("redirect:/users/"))
142+
.andDo(print())
143+
.andReturn();
144+
}
145+
146+
@Test
147+
public void deleteUser() throws Exception {
148+
mockMvc.perform( MockMvcRequestBuilders.delete("/users/delete/{id}", 1L) )
149+
.andDo(print())
150+
.andExpect(status().is(HttpServletResponse.SC_FOUND))
151+
.andExpect(view().name("redirect:/users/"));
152+
}
153+
154+
public static byte[] convertObjectToJsonBytes(Object object) throws IOException {
155+
ObjectMapper mapper = new ObjectMapper();
156+
mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
157+
return mapper.writeValueAsBytes(object);
158+
}
159+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
## 开启 H2 数据库
2+
spring.h2.console.enabled=true
3+
4+
## 配置 H2 数据库连接信息
5+
spring.datasource.url=jdbc:h2:mem:testdb
6+
spring.datasource.driverClassName=org.h2.Driver
7+
spring.datasource.username=sa
8+
spring.datasource.password=
9+
10+
11+
## 是否显示 SQL 语句
12+
spring.jpa.show-sql=true
13+
hibernate.dialect=org.hibernate.dialect.H2Dialect
14+
hibernate.hbm2ddl.auto=create
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
/* contentDiv */
2+
.contentDiv {padding:20px 60px;}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
<!DOCTYPE html>
2+
<html lang="zh-CN">
3+
<head>
4+
<script type="text/javascript" th:src="@{https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js}"></script>
5+
<link th:href="@{https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css}" rel="stylesheet"/>
6+
<link th:href="@{/css/default.css}" rel="stylesheet"/>
7+
<link rel="icon" th:href="@{/images/favicon.ico}" type="image/x-icon"/>
8+
<meta charset="UTF-8"/>
9+
<title>用户管理</title>
10+
</head>
11+
12+
<body>
13+
<div class="contentDiv">
14+
15+
<h5> 《 Spring Boot 2.x 核心技术实战》第二章快速入门案例</h5>
16+
17+
<legend>
18+
<strong>用户管理</strong>
19+
</legend>
20+
21+
<form th:action="@{/users/{action}(action=${action})}" method="post" class="form-horizontal">
22+
23+
<input type="hidden" name="id" th:value="${user.id}"/>
24+
25+
<div class="form-group">
26+
<label for="user_name" class="col-sm-2 control-label">名称:</label>
27+
<div class="col-xs-4">
28+
<input type="text" class="form-control" id="user_name" name="name" th:value="${user.name}" th:field="*{user.name}" />
29+
</div>
30+
<label class="col-sm-2 control-label text-danger" th:if="${#fields.hasErrors('user.name')}" th:errors="*{user.name}">姓名有误!</label>
31+
</div>
32+
33+
<div class="form-group">
34+
<label for="user_age" class="col-sm-2 control-label">年龄:</label>
35+
<div class="col-xs-4">
36+
<input type="text" class="form-control" id="user_age" name="age" th:value="${user.age}" th:field="*{user.age}" />
37+
</div>
38+
<label class="col-sm-2 control-label text-danger" th:if="${#fields.hasErrors('user.age')}" th:errors="*{user.age}">年龄有误!</label>
39+
</div>
40+
41+
<div class="form-group">
42+
<label for="user_birthday" class="col-sm-2 control-label">出生日期:</label>
43+
<div class="col-xs-4">
44+
<input type="date" class="form-control" id="user_birthday" name="birthday" th:value="${user.birthday}" th:field="*{user.birthday}"/>
45+
</div>
46+
<label class="col-sm-2 control-label text-danger" th:if="${#fields.hasErrors('user.birthday')}" th:errors="*{user.birthday}">生日有误!</label>
47+
</div>
48+
49+
<div class="form-group">
50+
<div class="col-sm-offset-2 col-sm-10">
51+
<input class="btn btn-primary" type="submit" value="提交"/>&nbsp;&nbsp;
52+
<input class="btn" type="button" value="返回" onclick="history.back()"/>
53+
</div>
54+
</div>
55+
</form>
56+
</div>
57+
</body>
58+
</html>

0 commit comments

Comments
 (0)