回顧
在前文Spring Boot下編寫Controller層單元測(cè)試(一)中调榄,我們用Spring MVC框架寫了一個(gè)最簡(jiǎn)單的REST接口芝此,其中沒有涉及業(yè)務(wù)邏輯。
在本文中我將繼續(xù)深入,將業(yè)務(wù)邏輯加入到項(xiàng)目中,并展示如何進(jìn)行測(cè)試档桃。
增加Service層代碼
首先定義一個(gè)接口,在我們簡(jiǎn)單項(xiàng)目中是否定義接口其實(shí)并不重要憔晒,但這依然是個(gè)好習(xí)慣藻肄。
public interface IDemoService {
List<Demo> findAll();
}
增加DemoService實(shí)現(xiàn)層代碼
@Service
public class DemoService implements IDemoService{
@Override
public List<Demo> findAll() {
return null;
}
}
Controller層調(diào)用業(yè)務(wù)邏輯
接下來我們要在Controller層調(diào)用demoService
@Controller
@RequestMapping("demos")
public class DemoController {
private IDemoService demoService;
@Autowired
public DemoController(IDemoService demoService) {
this.demoService = demoService;
}
@GetMapping
public ResponseEntity<List> searchDemo() {
List<Demo> demoList = demoService.findAll();
return new ResponseEntity<>(demoList, HttpStatus.OK);
}
}
修改單元測(cè)試
修改完業(yè)務(wù)代碼之后直接運(yùn)行原來的測(cè)試代碼,會(huì)發(fā)現(xiàn)拋出NullPointException
這是因?yàn)闇y(cè)試的searchDemo()
方法需要調(diào)用demoService
對(duì)象拒担,而在我們的測(cè)試類中沒有創(chuàng)建demoService
對(duì)象嘹屯。
@RunWith(MockitoJUnitRunner.class)
public class MockDemoControllerTest {
private MockMvc mockMvc;
@InjectMocks
private DemoController demoController;
@Mock // 創(chuàng)建一個(gè)模擬的demoService對(duì)象
private DemoService demoService;
?
@Before
public void setUp() throws Exception {
mockMvc = MockMvcBuilders.standaloneSetup(demoController).build();
}
@Test
public void should_get_demos() throws Exception {
mockMvc.perform(get("/demos"))
.andExpect(status().isOk());
}
}
修改的測(cè)試代碼很簡(jiǎn)單,只增加了@Mock private DemoService demoService
从撼。
執(zhí)行修改后的測(cè)試代碼州弟,將會(huì)看到我們的測(cè)試結(jié)果再次變綠。
發(fā)生了什么
相比較與前一個(gè)版本低零,發(fā)生了什么改變呢婆翔?
首先我們測(cè)試的類DemoController
多了一個(gè)依賴的對(duì)象demoService
,并且在測(cè)試的方法中還需要調(diào)用demoService
的findAll()
方法掏婶。但在原來的測(cè)試中浙滤,demoController
對(duì)象中并沒有找到所的demoService
對(duì)象。
為什么增加@Mock private DemoService demoService
之后就可以正常運(yùn)行了气堕?
關(guān)鍵要看使用@InjectMocks
與@Mock
這兩個(gè)注解后發(fā)生了什么。
@InjectMocks與@Mock
private DemoService demoService1 = new DemoService();
/**
* 可以簡(jiǎn)單的理解為 增加這個(gè)注解后
* 執(zhí)行了 private DemoService demoService2 = new DemoService();
*/
@Mock
private DemoService demoService2;
/**
* @InjectMocks注解可以理解為
* 執(zhí)行了 private DemoController demoController = new DemoController(demoService2);
*/
@InjectMocks
private DemoController demoController;
也就是說畔咧,MockitoJUnitRunner
執(zhí)行器在運(yùn)行前會(huì)檢測(cè)到使用@InjectMocks
和@Mock
的成員變量茎芭,并自動(dòng)為其創(chuàng)建對(duì)象。
總結(jié)
本文在創(chuàng)建REST接口的基礎(chǔ)上增加了業(yè)務(wù)邏輯誓沸,更加貼近實(shí)際生產(chǎn)環(huán)境梅桩。針對(duì)代碼結(jié)構(gòu)改變,相應(yīng)改變了測(cè)試代碼拜隧,解決待測(cè)試代碼的依賴問題宿百。
解釋了測(cè)試代碼中用到的兩個(gè)注解作用趁仙,但沒有對(duì)其深入展開。
下一篇我將繼續(xù)介紹如何測(cè)試Controller代碼垦页,并介紹一下其他的測(cè)試用法雀费。