兩個基於spring的單元測試簡單樣例

  單元測試,從必定程度上能夠看出一個同窗達到的層次。但又不徹底是,有時可能只是一個思考方式的轉變。單元測試有很是多的工具供選擇,在java中,junit無疑是比較經常使用的。本文列出,junit在spring中的使用樣例,供參考。java

 

1. 單元測試主要方式

  這裏僅說咱們經常使用的單元測試的場景,或者是我本身經常使用的場景,主要分爲4大類:web

    1. 對外提供的接口級別的測試,如rest-api, 主要用於保證對外提供的接口符合預期, 而非等到別人調用時才發現異常; spring

    2. serivce 級別的單元測試, 主要用於保證service功能正常;json

    3. 靜態方法的測試, 主要用於測試一些工具類符合預期,這類測試通常比較簡單;api

    4. mock接口實現測試, 這類測試每每最複雜, 通常是爲測試複雜場景, 但又要保證影響因素單一, 保證測試的有效性, 要求既要mock得少也要求mock得合適, 最難;springboot

  實際上,除了最後一種測試是比較體系化和完備的以外,前幾種也許都不是那麼細緻,至少通常測試不到某個很小的點上,或者說場景不一致。但記住一點,單元測試應該基於行爲,而非基於實現。mvc

 

2. springmvc 的單元測試樣例

  這裏主要說的是低版本的springmvc, 裏面依賴還比較原始, 因此須要單獨講講。其依賴包可以下參考:app

        <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的配置就行,不然可能找不到對應的controller)框架

@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration({"classpath:applicationContext.xml",
                        "classpath:applicationContext-servlet.xml"})
public class SpringMvcTest {

    @Autowired
    private WebApplicationContext wac;

    private MockMvc mockMvc;

    @Before
    public void before() throws Exception {
        mockMvc = MockMvcBuilders.webAppContextSetup(wac).build();
    }

    // 對外提供的接口級別的測試
    @Test
    public void testMetaDataAddSensitiveKeyword() 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("接口返回結果:" + responseResult);
        resultObj = JSONObject.parseObject(responseResult);
        Assert.assertNotNull("響應結果爲空", resultObj);
        Assert.assertThat("正常插入失敗",
                resultObj.getInteger("status"), is(1));

    }

    
    @Resource
    private TestService testService;
    
    // serivce 級別的單元測試
    @Test
    public void testPureExternalIndexDataSensitiveKeyword() {
        TestObj tObj = new TestObj();
        tObj.setXXX(302L);
        try {
            testService.checkKeyWord(tObj);
        }
        catch (BizException e) {
            Assert.assertEquals("錯誤碼返回不正確", 4001021, e.getErrCode());
        }
    }

    // 靜態方法的測試
    @Test
    public void testUiExtract() {
        String ruleEL;
        ParsedClause parsedClause;

        ruleEL = "ui_extract($123, 'md') = '02-01'";

        parsedClause = SyntaxParser.parse(ruleEL);

        Assert.assertEquals("數量解析不正確",
                1, parsedClause.getLabelIdMapping().size());
        Assert.assertEquals("解析UPP結果不正確",
                "string.substring($123 , 5, 10) = '02-01'",
                parsedClause.translateTo(DialectTypeEnum.ES));
        Assert.assertEquals("解析結果不正確",
                "substr($123 , 5, 5) = '02-01'",
                parsedClause.translateTo(DialectTypeEnum.HIVE));

    }

    // mock接口實現測試
    @Test
    public void testMockInterface() {

        List mockList = Mockito.mock(List.class);
        mockList.add("1");
        // 返回null,說明並無調用真正的方法
        Assert.assertNull("mock沒有返回null", mockList.get(0));
        Mockito.when(mockList.size()).thenReturn(100);//stub
        // size() method was stubbed,返回100
        Assert.assertThat("mock.size未返回預期值",
                    mockList.size(), is(100));

        //test for Spy
        List 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 methods
        spy.add("one");
        spy.add("two");

        //prints "one" - the first element of a list
        System.out.println(spy.get(0));

        //size() method was stubbed - 100 is printed
        System.out.println(spy.size());
    }

    // 預期發生異常的場景測試
    @Test(expected = BizException.class)
    public void testMethodThrow() {
        SyntaxParser.parse(null);
    }

}

  即對上面4種場景的簡單實現樣例。spring-boot

 

3. springboot的單元測試樣例

  springboot爲咱們省去了許多的依賴問題,因此不會很麻煩。只需引入 test 包,其餘相應依賴就下來了。並且通常都是demo代碼裏默認帶有的依賴:

        <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
@AutoConfigureMockMvc
public class DemoBatchDataControllerTest {

    @Autowired
    private MockMvc mockMvc;

    @Test
    public void testApi1() throws Exception {
        MvcResult result = mockMvc.perform(get("/demo/test1"))
                            .andExpect(status().isOk())
                            .andReturn();
        Assert.assertThat("結果不正確", 
                result.getResponse().getContentAsString(), containsString("ok"));
    }

    // 其餘同springmvc


}

  可見springboot確實簡單了許多。但框架始終只是框架,須要用戶注入靈魂,才能在其上面玩出花樣來。

  測試驅動或者測試先行開發,是一種比較好的實踐,可讓咱們少走彎路,且更自信。

相關文章
相關標籤/搜索