SpringBoot單元測試


針對不同的代碼層次, 有不同的測試注意事項.

我的理解是:

針對Mapper層或者是Dao層,由於需要跟數據庫交互, 寫完代碼的時候手工執行就好, 由於數據庫的數據的不穩定性,不適合用作大量回歸測試.

針對Service層的單元測試才是我們通常理解的那種單元測試或者說白盒測試.

針對Controller層的測試,如果Mock了Service層的行為,那這個算是白盒測試,如果沒有Mock Service層行為,而是直接調用,我覺得其實已經可以算是集成測試了,這個偏向黑盒測試的范疇,就是我們通常說的API測試.

 

1. 針對Mapper層或者Dao層

如果是有依賴其他Bean對象,可以先寫一個專門用來裝配Bean的類,並用注解TestConfiguration標注.

當然,這一步也不是必須的,這個只是為了方便在單元測試類中使用@Autowired引入對象.可以在單元測試類中,使用Product product = new Product()代替.

 1 import org.springframework.boot.test.context.TestConfiguration;
 2 import org.springframework.context.annotation.Bean;
 3 
 4 import com.windy.mall.product.bean.Product;
 5 
 6 @TestConfiguration
 7 public class TestBeanConfiguration {
 8 
 9     @Bean
10     public Product createProduct(){
11         return new Product();
12     }
13     
14 }
View Code

 

單元測試類中必須要聲明:

(1) @RunWith(Spring.class),表示要在Spring環境中做測試, 於是就可以使用@Autowired等注解了,

(2) @SpringBootTest(classes=TestBeanConfiguration.class),表示可以使用SpringBoot環境了,這樣可以用@Autowired注解,把@Mapper注釋過的Mapper對象引入.為了引入外部依賴的Bean對象,需要指定classes=TestBeanConfiguration.class.

注意: 之所以要指定classes=TestBeanConfiguration.class,這時因為Product這個類,並沒有使用@Component等注解注入IOC容器.

可選:

(3) @Transactional注解來開啟事務

(4) @Rollback(true)表示開啟回滾數據功能,默認為True.

 1 import org.junit.Assert;
 2 import org.junit.Before;
 3 import org.junit.Test;
 4 import org.junit.runner.RunWith;
 5 import org.springframework.beans.factory.annotation.Autowired;
 6 import org.springframework.boot.test.context.SpringBootTest;
 7 import org.springframework.test.annotation.Rollback;
 8 import org.springframework.test.context.junit4.SpringRunner;
 9 import org.springframework.transaction.annotation.Transactional;
10 
11 import com.windy.mall.product.bean.Product;
12 import com.windy.mall.product.bean.TestBeanConfiguration;
13 
14 @RunWith(SpringRunner.class)
15 @SpringBootTest(classes=TestBeanConfiguration.class)
16 @Transactional
17 @Rollback(true)
18 public class ProductMapperTest {
19 
20     @Autowired
21     private ProductMapper mapper;
22     
23     @Autowired
24     private Product product;
25     
26     @Before
27     public void setUp(){
28         product.setPname("持續交付");
29         product.setType("書籍");
30         product.setPrice(69d);
31     }
32     
33     @Test
34     public void testAdd() {
35         Assert.assertEquals(Integer.valueOf(1), mapper.add(product));
36     }
37 
38 }
View Code

 

 

2. 針對Service層

由於Service層需要調用Mapper層或者是Dao層,通常需要Mock Mapper對象.這里需要使用到@MockBean注解,Mock Mapper層的行為.

 1 package com.windy.mall.product.service;
 2 
 3 import org.junit.Assert;
 4 import org.junit.Before;
 5 import org.junit.Test;
 6 import org.junit.runner.RunWith;
 7 import org.mockito.BDDMockito;
 8 import org.springframework.beans.factory.annotation.Autowired;
 9 import org.springframework.boot.test.context.SpringBootTest;
10 import org.springframework.boot.test.mock.mockito.MockBean;
11 import org.springframework.test.context.junit4.SpringRunner;
12 
13 import com.windy.mall.product.bean.Product;
14 import com.windy.mall.product.bean.TestBeanConfiguration;
15 import com.windy.mall.product.mapper.ProductMapper;
16 
17 @RunWith(SpringRunner.class)
18 @SpringBootTest(classes = TestBeanConfiguration.class)
19 public class ProductServiceTest {
20 
21     @MockBean
22     private ProductMapper mapper;
23 
24     @Autowired
25     private Product product;
26 
27     @Autowired
28     private ProductService service;
29 
30     @Before
31     public void setUp() {
32         BDDMockito.given(mapper.add(product)).willReturn(1);
33         BDDMockito.given(mapper.add(null)).willReturn(0);
34     }
35 
36     @Test
37     public void testAddService() {
38         Assert.assertEquals(Integer.valueOf(1), service.add(product));
39         Assert.assertEquals(Integer.valueOf(0), service.add(null));
40     }
41 
42 }
View Code

 

3.針對Controller

有兩種方法可以做單元測試:

(1) 這里需要用到web環境(webEnvironment=WebEnvironment.RANDOM_PORT).需要用到TestRestTemplate這個對象作為客戶方,調用Controller(API)

 1 import org.junit.Assert;
 2 import org.junit.Test;
 3 import org.junit.runner.RunWith;
 4 import org.springframework.beans.factory.annotation.Autowired;
 5 import org.springframework.boot.test.context.SpringBootTest;
 6 import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
 7 import org.springframework.boot.test.web.client.TestRestTemplate;
 8 import org.springframework.test.context.junit4.SpringRunner;
 9 
10 @RunWith(SpringRunner.class)
11 @SpringBootTest(webEnvironment=WebEnvironment.RANDOM_PORT)
12 public class ProductControllerTest {
13 
14     @Autowired
15     private TestRestTemplate template;
16     
17     @Test
18     public void test() {
19         String body = template.getForObject("/ms/product/1", String.class);
20         Assert.assertEquals("success", body);
21     }
22 
23 }
View Code

 

(2) 如果是使用MockMVC對象來測試,需要開啟@AutoConfigureMockMvc注解

 1 import org.junit.Test;
 2 import org.junit.runner.RunWith;
 3 import org.springframework.beans.factory.annotation.Autowired;
 4 import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
 5 import org.springframework.boot.test.context.SpringBootTest;
 6 import org.springframework.test.context.junit4.SpringRunner;
 7 import org.springframework.test.web.servlet.MockMvc;
 8 import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
 9 import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
10 
11 @RunWith(SpringRunner.class)
12 @SpringBootTest
13 @AutoConfigureMockMvc
14 public class ProductControllerTest2 {
15 
16     @Autowired
17     private MockMvc mvc;
18 
19     @Test
20     public void test() throws Exception {
21         mvc.perform(MockMvcRequestBuilders.get("/ms/product/1"))
22                 .andExpect(MockMvcResultMatchers.status().isOk())
23                 .andExpect(MockMvcResultMatchers.content().string("success"));
24     }
25 
26 }
View Code

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM