【高效編碼】深入TestNG體驗(yàn)了一把,真爽
您好,我是碼農(nóng)飛哥,感謝您閱讀本文!如果此文對您有所幫助,請毫不猶豫的一鍵三連吧。小伙伴們,有啥想看的,想問的,歡迎積極留言。上一篇文章對TestNG做了一個簡單的體驗(yàn)。我們了解了其是什么,有什么用,重點(diǎn)介紹了其各種注解。但是這些都不夠深入,不夠爽。實(shí)際項(xiàng)目中怎么運(yùn)用呢?沒有說,實(shí)在不過癮。
這篇文章就讓我們來深入體驗(yàn)一下TestNG??纯吹降缀貌缓糜?,用的爽不爽。
文章目錄
搭建項(xiàng)目,添加待測試類
引入依賴
編寫單元測試基類
編寫單元測試方法
并發(fā)測試
總結(jié)
搭建項(xiàng)目,添加待測試類
首先,還是搭建一個SpringBoot框架的項(xiàng)目,怎么搭建項(xiàng)目,在此就不贅述了,想了解的朋友可以參考這篇文章Spring Boot 學(xué)習(xí)01-----搭建一個簡單的spring-boot-demo
項(xiàng)目搭建好之后,這里添加了幾個待測試的方法。代碼如下:
@RestController public class TestNgController { @Autowired private TestNgService testNgService; @PostMapping("/v1/user/add") public String addUser(String userName, String password) { boolean result = testNgService.saveUser(userName, password); return result ? "{\"code\":\"200\",\"msg\":\"用戶保存成功\"}" : "{\"code\":\"500\",\"msg\":\"用戶保存失敗\"}"; } @GetMapping("/v1/user/get") public String getUser(String userName) { boolean result = testNgService.getUserByName(userName); return "{\"code\":\"200\",\"msg\":\"獲取用戶成功\"}"; } @RequestMapping("/v1/user/update") public String updateUser(@RequestBody User user) { boolean result = testNgService.updateUser(user); return result ? "{\"code\":\"200\",\"msg\":\"用戶修改成功\"}" : "{\"code\":\"500\",\"msg\":\"用戶修改失敗\"}"; } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
這里分別有:
用戶保存接口/v1/user/add,請求類型是application/form-data。
獲取用戶接口/v1/user/get,請求類型是application/form-data。
用戶更新接口/v1/user/update ,這個的請求類型是application/json
三個接口,下面分別對這三個接口進(jìn)行單元測試。
引入依賴
針對接口的測試需要引入的依賴有,spring-boot-starter-test主要是引入Spring-Test 依賴,因?yàn)樾枰褂?@SpringBootTest,testng依賴就不用多說了,今日份主角。
1
2
3
4
5
6
7
8
9
10
11
編寫單元測試基類
設(shè)置單元測試基類
@SpringBootTest public class TestNgControllerTest extends AbstractTestNGSpringContextTests { private MockMvc mockMvc; @Autowired private WebApplicationContext webApplicationContext; @BeforeClass public void setUp(){ //必須用webAppContextSetup方法設(shè)置web環(huán)境 this.mockMvc = MockMvcBuilders.webAppContextSetup(this.webApplicationContext).build(); } //通用返回結(jié)果的封裝 public String getResultCode(MockHttpServletRequestBuilder requestBuilder) { try { MvcResult mvcResult = mockMvc.perform(requestBuilder) .andDo(print()) .andExpect(status().isOk()) .andReturn(); String result = mvcResult.getResponse().getContentAsString(); JSONObject jsonObject = JSON.parseObject(result); return jsonObject.getString("code"); } catch (Exception e) { e.printStackTrace(); } return null; } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
是不是感覺跟前面Junit 整合SpringBoot的單元測試基類有點(diǎn)像呢?對的沒錯,長的確實(shí)有點(diǎn)像,因?yàn)槠渲蠱vcResult對象和MockMvc對象因?yàn)閬碜詓pring-test。所以,getResultCode方法是一模一樣的,都是針對返回類型是application/json格式的返回做了處理。
需要特別注意的是與Junit的不同點(diǎn):
繼承AbstractTestNGSpringContextTests 類。
因?yàn)檫@個類實(shí)現(xiàn)了ApplicationContextAware接口(Spring會檢查實(shí)現(xiàn)該接口的類,并通過setApplicationContext方法注入ApplicationContext對象)??梢垣@取到這個ApplicationContext系統(tǒng)上下文對象,而WebApplicationContext對象是ApplicationContext對象的子類。
通過 @BeforeClass 注解修飾的方法來初始化MockMvc對象。
最主要的原因是AbstractTestNGSpringContextTests類中通過springTestContextPrepareTestInstance來準(zhǔn)備初始化的對象
@BeforeClass(alwaysRun = true, dependsOnMethods = "springTestContextBeforeTestClass") protected void springTestContextPrepareTestInstance() throws Exception { this.testContextManager.prepareTestInstance(this); }
1
2
3
所以在@BeforeClass運(yùn)行之前執(zhí)行的方法都不能獲取對象。即使用@BeforeSuite或者是@BeforeTest注解修飾的話,則初始化方法運(yùn)行時ApplicationContext還沒有被注入進(jìn)來。如果用@BeforeMethod修飾的話,則每個測試方法執(zhí)行之前都會執(zhí)行一次。
補(bǔ)充說明:@BeforeClass(alwaysRun = true, dependsOnMethods = "springTestContextBeforeTestClass") dependsOnMethods屬性表示該方法依賴于springTestContextBeforeTestClass方法,就是說springTestContextBeforeTestClass必須要先于springTestContextPrepareTestInstance執(zhí)行,同時alwaysRun = true 表示依賴者和被依賴者之間必須不存在成功失敗的因果關(guān)系,只需要被依賴的方法執(zhí)行即可。
編寫單元測試方法
基類編寫好之后,就相當(dāng)于是打好了基礎(chǔ),下面只要搬磚了。首先編寫保存用戶的測試方法
@Test public void testAddUser() { System.out.println("線程="+Thread.currentThread().getName()+"執(zhí)行testAddUser"); //保存成功 { MockHttpServletRequestBuilder requestBuilder = MockMvcRequestBuilders.post("/v1/user/add") .param("userName", "張三") .param("password", "123"); String resultCode = getResultCode(requestBuilder); Assert.assertEquals("200", resultCode); } //保存失敗的情況 { MockHttpServletRequestBuilder requestBuilder = MockMvcRequestBuilders.post("/v1/user/add") .param("userName", "李四") .param("password", "123"); String resultCode = getResultCode(requestBuilder); Assert.assertEquals("500", resultCode); } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
這里有保存成功和保存失敗兩種情況。代碼的編寫跟使用Junit時是一模一樣的,還是實(shí)例化MockHttpServletRequestBuilder對象,傳入接口地址和入?yún)ⅰT诖瞬辉谫樖隽恕?zhí)行結(jié)果是:
直接運(yùn)行單元測試類,三個測試方法的運(yùn)行線程都是主線程,不是說testNG可以進(jìn)行并發(fā)測試么?沒看到呀,不要著急,這就來進(jìn)行并發(fā)測試。
并發(fā)測試
建立一個TestNG的XML文件,命名為TestNgControllerTestSuite.xml。
1
2
3
4
5
6
7
8
其中與并發(fā)測試相關(guān)的配置是:
1
在當(dāng)前測試規(guī)劃的執(zhí)行過程中,為每個方法(不管是不是通過@Test修飾的方法)進(jìn)行并發(fā)執(zhí)行,最多4個線程,下面就是運(yùn)行結(jié)果
當(dāng)然還有其他的配置,比如:
針對測試方法
1
在當(dāng)前測試規(guī)劃的執(zhí)行過程中,為每個測試方法(只有通過@Test修飾的方法)進(jìn)行并發(fā)執(zhí)行,最多4個線程。
2. 針對測試類
1
在當(dāng)前測試規(guī)劃的執(zhí)行過程中,為每個測試類的執(zhí)行使用單獨(dú)的線程(該測試類中的測試方法共享一個線程),最多并發(fā)4個線程。
總結(jié)
本文詳細(xì)介紹了TestNG與SpringBoot的整合,還介紹了并發(fā)測試。
Spring Spring Boot
版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實(shí)的內(nèi)容,請聯(lián)系我們jiasou666@gmail.com 處理,核實(shí)后本網(wǎng)站將在24小時內(nèi)刪除侵權(quán)內(nèi)容。