目錄
本文將對在Springboot中如何使用Junit進行單元測試進行簡單示例和介紹,項目的完整目錄層次如下圖所示。
添加依賴與配置
為了保證測試的完整性,本工程POM文件中除引入Junit單元測試依賴外,還額外引入了用來測試JDBC和Controller的JPA和WEB依賴。
-
<parent>
-
<groupId>org.springframework.boot
</groupId>
-
<artifactId>spring-boot-starter-parent
</artifactId>
-
<version>1.5.6.RELEASE
</version>
-
</parent>
-
-
<dependencies>
-
<!-- 添加MySQL依賴 -->
-
<dependency>
-
<groupId>mysql
</groupId>
-
<artifactId>mysql-connector-java
</artifactId>
-
</dependency>
-
<!-- 添加JDBC依賴 -->
-
<dependency>
-
<groupId>org.springframework.boot
</groupId>
-
<artifactId>spring-boot-starter-data-jpa
</artifactId>
-
</dependency>
-
<dependency>
-
<groupId>org.springframework.boot
</groupId>
-
<artifactId>spring-boot-starter-web
</artifactId>
-
</dependency>
-
<!-- 引入單元測試依賴 -->
-
<dependency>
-
<groupId>org.springframework.boot
</groupId>
-
<artifactId>spring-boot-starter-test
</artifactId>
-
<scope>test
</scope>
-
</dependency>
-
</dependencies>
同時,在src/main/resources目錄下添加核心配置文件application.properties,內容如下。
-
#########################################################
-
### Spring DataSource
-- DataSource configuration ###
-
#########################################################
-
spring.datasource.url=jdbc:mysql://localhost:3306/dev1?useUnicode=true&characterEncoding=utf8
-
spring.datasource.driverClassName=com.mysql.jdbc.Driver
-
spring.datasource.username=root
-
spring.datasource.password=123456
-
-
#########################################################
-
### Java Persistence Api
-- Spring jpa configuration ###
-
#########################################################
-
# Specify the DBMS
-
spring.jpa.database = MYSQL
-
#
Show
or
not
log
for
each
sql
query
-
spring.jpa.show-
sql =
true
-
# Hibernate
ddl
auto (
create,
create-
drop,
update)
-
spring.jpa.hibernate.ddl-
auto =
update
-
# Naming strategy
-
#[org.hibernate.cfg.ImprovedNamingStrategy #org.hibernate.cfg.DefaultNamingStrategy]
-
spring.jpa.hibernate.naming-strategy = org.hibernate.cfg.ImprovedNamingStrategy
-
# stripped
before adding them
to the entity manager)
-
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5Dialect
ApplicationContext測試
在Springboot中使用Junit進行單元測試的方法很簡單,只需要在編寫的單元測試類上添加兩個注解:@RunWith(SpringRunner.class)和@SpringBootTest。
-
@RunWith(SpringRunner.class)
// 等價於使用 @RunWith(SpringJUnit4ClassRunner.class)
-
@SpringBootTest(classes = { MyApplication.class, TestConfig.class })
-
public
class ApplicationContextTest {
-
-
@Autowired
-
private ApplicationContext context;
-
-
@Autowired
-
private UserDao userDao;
-
-
@Test
-
public void testUserDao() {
-
userDao.addUser(
18,
"pengjunlee");
-
}
-
-
@Test
-
public void testConfiguration() {
-
Runnable bean = context.getBean(Runnable.class);
-
Assert.assertNotNull(bean);
-
bean.run();
-
}
-
-
}
UserDao定義如下。
-
@Repository
-
public
class UserDao {
-
-
@Autowired
-
private JdbcTemplate jdbcTemplate;
-
-
@Transactional
-
public void addUser(Integer userAge, String userName) {
-
String sql =
"insert into tbl_user (age,name) values ('" + userAge +
"','" + userName +
"');";
-
jdbcTemplate.execute(sql);
-
}
-
}
TestConfig定義如下。
-
/**
-
* @TestConfiguration注解的配置內的Bean僅在測試時裝配
-
*/
-
@TestConfiguration
-
public
class TestConfig {
-
-
@Bean
-
public Runnable createRunnable(){
-
return ()->{
-
System.out.println(
"This is a test Runnable bean...");
-
};
-
}
-
}
提示:@SpringBootTest注解的classes可以指定用來加載Spring容器所使用的配置類,@TestConfiguration注解修飾的配置類內的Bean僅在測試的時候才會裝配。
Environment測試
我們可以通過@SpringBootTest注解的properties屬性向Environment中設置新的屬性,也可以通過使用EnvironmentTestUtils工具類來向ConfigurableEnvironment中添加新的屬性。
-
@RunWith(SpringRunner.class)
-
@SpringBootTest(properties = {
"app.token=pengjunlee" })
-
public
class EnvironmentTest {
-
-
@Autowired
-
private Environment env;
-
-
@Autowired
-
private ConfigurableEnvironment cenv;
-
-
@Before
-
public void init() {
-
EnvironmentTestUtils.addEnvironment(cenv,
"app.secret=55a4b77eda");
-
}
-
-
@Test
-
public void testEnvironment() {
-
System.out.println(env.getProperty(
"spring.datasource.url"));
-
Assert.assertEquals(
"pengjunlee", env.getProperty(
"app.token"));
-
Assert.assertEquals(
"55a4b77eda", cenv.getProperty(
"app.secret"));
-
}
-
-
@Test
-
@Ignore
// 忽略測試方法
-
public void testIgnore() {
-
-
System.out.println(
"你看不見我...");
-
}
-
-
}
擴展:Junit測試用例執行順序:@BeforeClass ==> @Before ==> @Test ==> @After ==> @AfterClass 。
注意:在使用Junit對Spring容器進行單元測試時,若在src/test/resources 目錄下存在核心配置文件,Spring容器將會只加載src/test/resources 目錄下的核心配置文件,而不再加載src/main/resources 目錄下的核心配置文件。
MockBean測試
我們可以通過@MockBean注解來對那些未添加實現的接口進行模擬測試,預先設定好調用方法期待的返回值,然后再進行測試。
例如,有如下的IUserService接口,定義了一個getUserAge()方法用來根據用戶的ID來查詢用戶的年齡。
-
public
interface IUserService {
-
-
Integer getUserAge(Long userId);
-
-
}
使用@MockBean來對IUserService接口進行模擬測試,測試代碼如下。
-
@RunWith(SpringRunner.class)
-
public
class MockBeanTest {
-
-
@MockBean
-
private IUserService userService;
-
-
@SuppressWarnings(
"unchecked")
-
@Test(expected = NullPointerException.class)
-
public void testMockBean() {
-
-
BDDMockito.given(userService.getUserAge(
2L)).willReturn(Integer.valueOf(
18));
-
BDDMockito.given(userService.getUserAge(
0L)).willReturn(Integer.valueOf(
0));
-
BDDMockito.given(userService.getUserAge(
null)).willThrow(NullPointerException.class);
-
-
Assert.assertEquals(Integer.valueOf(
18), userService.getUserAge(
2L));
-
Assert.assertEquals(Integer.valueOf(
0), userService.getUserAge(
0L));
-
Assert.assertEquals(Integer.valueOf(
0), userService.getUserAge(
null));
-
-
}
-
}
Controller測試
在Springboot中可以通過TestRestTemplate和MockMvc來對Controller進行測試,有以下兩種情況。
情況一
Controller中未裝配任何其他Spring容器中的Bean,例如下面這個控制器。
-
@RestController
-
@RequestMapping(
"/user")
-
public
class UserController01 {
-
-
@GetMapping(
"/home")
-
public String homeUser(@RequestParam(name = "name", required = true) String userName) {
-
if (
null == userName || userName.trim() ==
"") {
-
return
"you are nobody...";
-
}
-
return
"This is " + userName +
"'s home...";
-
}
-
}
此時無需啟動Spring容器,可直接使用MockMvc來對Controller進行模擬測試,測試代碼如下。
-
@RunWith(SpringRunner.class)
-
@WebMvcTest(controllers = { UserController01.class })
-
public
class ControllerTest01 {
-
-
@Autowired
-
private MockMvc mvc;
-
-
@Test
-
public void testAddUser() throws Exception {
-
mvc.perform(MockMvcRequestBuilders.get(
"/user/home").param(
"name",
""))
-
.andExpect(MockMvcResultMatchers.status().isOk())
-
.andExpect(MockMvcResultMatchers.content().string(
"you are nobody..."));
-
mvc.perform(MockMvcRequestBuilders.get(
"/user/home").param(
"name",
"pengjunlee"))
-
.andExpect(MockMvcResultMatchers.status().isOk())
-
.andExpect(MockMvcResultMatchers.content().string(
"This is pengjunlee's home..."));
-
}
-
-
}
情況二
Controller中需裝配其他Spring容器中的Bean,例如下面這個控制器。
-
@RestController
-
@RequestMapping(
"/user")
-
public
class UserController02 {
-
-
@Autowired
-
private UserDao userDao;
-
-
@GetMapping(
"/add")
-
public String addUser(@RequestParam(name = "age", required = false, defaultValue = "0") Integer userAge,
-
@RequestParam(name = "name", required = true) String userName) {
-
if (userAge <=
0 ||
null == userName || userName.trim() ==
"") {
-
return
"0";
-
}
-
userDao.addUser(userAge, userName);
-
return
"1";
-
}
-
-
}
此時除了要啟動Spring容器,還需要啟動內嵌的WEB環境,有以下兩種方法。
方法一
利用TestRestTemplate進行測試。
-
@RunWith(SpringRunner.class)
-
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
-
public
class ControllerTest02 {
-
-
@Autowired
-
private TestRestTemplate template;
-
-
@Test
-
public void testAddUser() {
-
String result1 = template.getForObject(
"/user/add?name=pengjunlee", String.class);
-
Assert.assertEquals(
"0", result1);
-
String result2 = template.getForObject(
"/user/add?age=20&name=Tracy", String.class);
-
Assert.assertEquals(
"1", result2);
-
}
-
-
}
方法二
利用MockMvc進行測試。
-
@RunWith(SpringRunner.class)
-
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
-
@AutoConfigureMockMvc
-
public
class ControllerTest03 {
-
-
@Autowired
-
private MockMvc mvc;
-
-
@Test
-
public void testAddUser() throws Exception {
-
mvc.perform(MockMvcRequestBuilders.get(
"/user/add").param(
"name",
""))
-
.andExpect(MockMvcResultMatchers.status().isOk())
-
.andExpect(MockMvcResultMatchers.content().string(
"0"));
-
mvc.perform(MockMvcRequestBuilders.get(
"/user/add").param(
"age",
"22").param(
"name",
"pengjunlee"))
-
.andExpect(MockMvcResultMatchers.status().isOk())
-
.andExpect(MockMvcResultMatchers.content().string(
"1"));
-
}
-
-
}
本文項目源碼已上傳至CSDN,資源地址:https://download.csdn.net/download/pengjunlee/10394302