兩個基于spring的單元測試簡單樣例
單元測試,從一定程度上可以看出一個同學(xué)達(dá)到的層次。但又不完全是,有時可能只是一個思考方式的轉(zhuǎn)變。單元測試有非常多的工具供選擇,在java中,junit無疑是比較常用的。本文列出,junit在spring中的使用樣例,供參考。
1:單元測試主要方式
這里僅說我們常用的單元測試的場景,或者是我自己常用的場景,主要分為4大類:
1. 對外提供的接口級別的測試,如rest-api, 主要用于保證對外提供的接口符合預(yù)期, 而非等到別人調(diào)用時才發(fā)現(xiàn)異常;
2. serivce 級別的單元測試, 主要用于保證service功能正常;
3. 靜態(tài)方法的測試, 主要用于測試一些工具類符合預(yù)期,這類測試一般比較簡單;
4. mock接口實(shí)現(xiàn)測試, 這類測試往往最復(fù)雜, 一般是為測試復(fù)雜場景, 但又要保證影響因素單一, 保證測試的有效性, 要求既要mock得少也要求mock得合適, 最難;
一般還有對環(huán)境初始化時的運(yùn)行,和結(jié)束測試時的清理工作,即setup() 和teardow(). 在junit中就體現(xiàn)為兩個注解:@Before 和 @After 。
實(shí)際上,除了最后一種測試是比較體系化和完備的之外,前幾種也許都不是那么細(xì)致,至少一般測試不到某個很小的點(diǎn)上,或者說場景不一致。api,service一般會涉及到復(fù)雜的外部系統(tǒng)調(diào)用,一是依賴多二是速度慢,而盡量保持本地化測試中一個最佳實(shí)踐。但記住一點(diǎn),單元測試應(yīng)該基于行為,而非基于實(shí)現(xiàn)。
2. springmvc 的單元測試樣例
這里主要說的是低版本的springmvc, 里面依賴還比較原始, 所以需要單獨(dú)講講。其依賴包可如下參考:
<dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version><scope>test</scope></dependency><dependency><groupId>org.hamcrest</groupId><artifactId>hamcrest-core</artifactId><version>1.3</version></dependency><dependency><groupId>org.hamcrest</groupId><artifactId>hamcrest-library</artifactId><version>1.3</version></dependency><dependency><groupId>org.mockito</groupId><artifactId>mockito-all</artifactId><version>1.9.5</version><scope>test</scope></dependency>
測試用例樣例如下:(主要注意必要時引用 servlet的配置就行,否則可能找不到對應(yīng)的controller)
@RunWith(SpringJUnit4ClassRunner.class)@WebAppConfiguration@ContextConfiguration({"classpath:applicationContext.xml","classpath:applicationContext-servlet.xml"})public class SpringMvcTest {@Autowiredprivate WebApplicationContext wac;private MockMvc mockMvc;@Beforepublic void before() throws Exception {mockMvc = MockMvcBuilders.webAppContextSetup(wac).build();}// 對外提供的接口級別的測試 @Before @After@Testpublic void tesaDataAddKeyword() throws Exception {TestObj tobj;MvcResult mvcResult;String responseResult;JSONObject resultObj;tobj = new TestObj();tobj.setXX(302L);mvcResult = mockMvc.perform(MockMvcRequestBuilders.post("/test/add").contentType("application/json").characterEncoding("utf-8").content(JSONObject.toJSONString(tobj))).andExpect(MockMvcResultMatchers.status().is(200)).andReturn();responseResult = mvcResult.getResponse().getContentAsString();System.out.println("接口返回結(jié)果:" + responseResult);resultObj = JSONObject.parseObject(responseResult);Assert.assertNotNull("響應(yīng)結(jié)果為空", resultObj);Assert.assertThat("正常插入失敗",resultObj.getInteger("status"), is(1));}@Resourceprivate TestService testService;// serivce 級別的單元測試@Testpublic void testPureKeyword() {TestObj tObj = new TestObj();tObj.setXXX(302L);try {testService.checkKeyWord(tObj);}catch (BizException e) {Assert.assertEquals("錯誤碼返回不正確", 4001021, e.getErrCode());}}// 靜態(tài)方法的測試@Testpublic void testUiExtract() {String ruleEL;ParsedClause parsedClause;ruleEL = "ui_extract($123, 'md') = '02-01'";parsedClause = SyntaxParser.parse(ruleEL);Assert.assertEquals("數(shù)量解析不正確",1, parsedClause.getLabelIdMapping().size());Assert.assertEquals("解析UPP結(jié)果不正確","string.substring($123 , 5, 10) = '02-01'",parsedClause.translateTo(DialectTypeEnum.ES));Assert.assertEquals("解析結(jié)果不正確","substr($123 , 5, 5) = '02-01'",parsedClause.translateTo(DialectTypeEnum.HIVE));}// mock接口實(shí)現(xiàn)測試@Testpublic void testMockInterface() {List mockList = Mockito.mock(List.class);mockList.add("1");// 返回null,說明并沒有調(diào)用真正的方法Assert.assertNull("mock沒有返回null", mockList.get(0));Mockito.when(mockList.size()).thenReturn(100);//stub// size() method was stubbed,返回100Assert.assertThat("mock.size未返回預(yù)期值",mockList.size(), is(100));//test for SpyList list = new LinkedList();List spy = Mockito.spy(list);//optionally, you can stub out some methods:Mockito.when(spy.size()).thenReturn(100);//using the spy calls real methodsspy.add("one");spy.add("two");//prints "one" - the first element of a listSystem.out.println(spy.get(0));//size() method was stubbed - 100 is printedSystem.out.println(spy.size());}// 預(yù)期發(fā)生異常的場景測試@Test(expected = BizException.class)public void testMethodThrow() {SyntaxParser.parse(null);}}
即對上面4種場景的簡單實(shí)現(xiàn)樣例。
3. springboot的單元測試樣例
springboot為我們省去了許多的依賴問題,所以不會很麻煩。只需引入 test 包,其他相應(yīng)依賴就下來了。而且一般都是demo代碼里默認(rèn)帶有的依賴:
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope><exclusions><exclusion><groupId>org.junit.vintage</groupId><artifactId>junit-vintage-engine</artifactId></exclusion></exclusions></dependency>
其使用樣例則也會更簡單,一個注解搞定了。
@RunWith(SpringRunner.class)@SpringBootTest@AutoConfigureMockMvcpublic class DemoBatchDataControllerTest {@Autowiredprivate MockMvc mockMvc;@Testpublic void testApi1() throws Exception {MvcResult result = mockMvc.perform(get("/demo/test1")).andExpect(status().isOk()).andReturn();Assert.assertThat("結(jié)果不正確",result.getResponse().getContentAsString(), containsString("ok"));}// 其他同springmvc}
可見springboot確實(shí)簡單了許多。但框架始終只是框架,需要用戶注入靈魂,才能在其上面玩出花樣來。
測試驅(qū)動或者測試先行開發(fā),是一種比較好的實(shí)踐,可以讓我們少走彎路,且更自信。

騰訊、阿里、滴滴后臺面試題匯總總結(jié) — (含答案)
面試:史上最全多線程面試題 !
最新阿里內(nèi)推Java后端面試題
JVM難學(xué)?那是因?yàn)槟銢]認(rèn)真看完這篇文章

關(guān)注作者微信公眾號 —《JAVA爛豬皮》
了解更多java后端架構(gòu)知識以及最新面試寶典


看完本文記得給作者點(diǎn)贊+在看哦~~~大家的支持,是作者源源不斷出文的動力
作者:等你歸去來
出處:https://www.cnblogs.com/yougewe/p/14540105.html
