一文彻底理解Java单元测试
Junit4
說(shuō)起Java中的單元測(cè)試,我覺(jué)得大家首先想到的應(yīng)該是Junit,比如下面這樣的一個(gè)類(lèi)和方法:
public class Calculator {public int evaluate(String expression) {int sum = 0;for (String summand: expression.split("\\+"))sum += Integer.valueOf(summand);return sum;} } 復(fù)制代碼我們可以編寫(xiě)一個(gè)測(cè)試類(lèi) CalculatorTest.java,來(lái)對(duì)方法Calculator.evaluate((String expression)進(jìn)行單元測(cè)試:
public class CalculatorTest {public void evaluatesExpression() {Calculator calculator = new Calculator();int sum = calculator.evaluate("1+2+3");Assert.assertEquals(6, sum);} } 復(fù)制代碼代碼如上,可以看到,使用一個(gè)注解 @Test和斷言語(yǔ)句Assert.assertEquals(6, sum);,便完成了一個(gè)單元測(cè)試的編寫(xiě)。
Test runners
一些常見(jiàn)的IDE都提供了對(duì)Junit的支持,可以直接在界面進(jìn)行測(cè)試,無(wú)需我們自己去控制臺(tái)run這些程序。
Junit默認(rèn)的runner是:BlockJUnit4ClassRunner,可以使用@RunWith注解來(lái)指定runner,比如后續(xù)我們需要用到的SpringJUnit4ClassRunner。
Assertions
上述例子中,要驗(yàn)證Calculator.evaluate的正確性,我們使用到了斷言語(yǔ)句 Assert.assertEquals(6, sum);,在平常的單元測(cè)試中,我們都需要編寫(xiě)大量的斷言語(yǔ)句。對(duì)于所有的基本類(lèi)型,Junit都提供了斷言方法,就像下面這樣:
public class AssertTests {public void testAssertNull() {assertNull("should be null", null);}public void testAssertTrue() {assertTrue("failure - should be true", true);} } 復(fù)制代碼Spring與Junit
在spring中,Spring TestContext Framework提供了對(duì)Junit的支持,通過(guò)使用@RunWith(SpringJUnit4ClassRunner.class)或@RunWith(SpringRunner.class)注解,我們便能實(shí)現(xiàn)一個(gè)標(biāo)準(zhǔn)的Junit測(cè)試,并且能獲取到Spring TestContext framework的支持,比如獲取spring context、事務(wù)管理、依賴(lài)注入等等。
@ContextConfiguration
@ContextConfiguration用來(lái)加載和配置一個(gè)ApplicationContext,可以用指定xml的方式,也可以指定一個(gè)config class:
("/test-config.xml") public class XmlApplicationContextTests {// class body... } (classes = TestConfig.class) public class ConfigClassApplicationContextTests {// class body... } 復(fù)制代碼即使用@RunWith(SpringRunner.class)和@ContextConfiguration,就可以起一個(gè)spring的環(huán)境并進(jìn)行測(cè)試了,如下:
(SpringRunner.class) (classes = CalculatorTest.TestConfig.class) public class CalculatorTest {private ApplicationContext applicationContext;public void application() {Assert.assertNotNull(applicationContext);Assert.assertNotNull(applicationContext.getBean("testBean"));}public static class TestConfig {public Object testBean() {return new Object();}} } 復(fù)制代碼Mock
在真實(shí)的測(cè)試場(chǎng)景中,一個(gè)類(lèi)往往會(huì)引用一個(gè)至多個(gè)bean,這些bean往往又會(huì)引用其他的bean,如果想在配置文件或類(lèi)中配置完所有的bean,發(fā)現(xiàn)會(huì)越寫(xiě)越多,最后可能需要一份全量的bean配置了。
public abstract class AbstractSplitPkgStrategy extends AbstractCostSplitStrategy {@Resourceprivate ISelfScItemAtomService selfScItemAtomService;@Resourceprivate GoodsCenterService goodsCenterService;@Resourceprivate CostItemSplitMapper costItemSplitMapper;@Resourceprivate SplitPkgByPcsMetaGenerateStrategy pcsStrategy;@Resourceprivate LstPackageReadService lstPackageReadService;@Resourceprivate TairManager commonTairManager;//方法... } 復(fù)制代碼比如上面是我們要進(jìn)行測(cè)試的一個(gè)類(lèi),當(dāng)我嘗試在xml或者config中配置它引用的bean的時(shí)候,我發(fā)現(xiàn)這些bean又引入了其他bean,然后得需要一層一層往下寫(xiě)配置。
Mockito
針對(duì)上述問(wèn)題,我們可以使用Mockito來(lái)mock掉我們需要的bean。mock的配置也有多種方式,如下是兩種配置方式:
使用xml進(jìn)行配置:
使用config class:
(SpringRunner.class) (classes = CalculatorTest.MockConfig.class) public class CalculatorTest {private Calculator calculator;public void application() {Assert.assertNotNull(calculator);}public static class MockConfig{public Calculator calculator() {return Mockito.mock(Calculator.class);}} } 復(fù)制代碼mock的使用:
(SpringRunner.class) (classes = CalculatorTest.MockConfig.class) public class CalculatorTest {private Calculator calculator;public void before() {Mockito.when(calculator.evaluate(Mockito.anyString())).thenReturn(1);}public void application() {Assert.assertEquals(1,calculator.evaluate("1+2"));Assert.assertEquals(1,calculator.evaluate("2+2"));}public static class MockConfig {public Calculator calculator() {return Mockito.mock(Calculator.class);}} } 復(fù)制代碼斷言
在上面,我們已經(jīng)看到了Junit提供的斷言方法,對(duì)于一些簡(jiǎn)單的場(chǎng)景,我覺(jué)得沒(méi)有什么問(wèn)題。但是在一些復(fù)雜的場(chǎng)景下,可能會(huì)導(dǎo)致代碼晦澀難懂。所以最后給大家介紹一個(gè)更好用的Java斷言框架— AssertJ。
比如下面這個(gè)比較簡(jiǎn)單的test:
用AssertJ之后的寫(xiě)法像下面這樣:
public void test() throws Exception {//ArrangeList<String> strings = Lists.newArrayList("a","b","c");//ActString removedString = strings.remove(0);//AssertassertThat(strings).contains("b", "c");復(fù)制代碼總結(jié)
以上是生活随笔為你收集整理的一文彻底理解Java单元测试的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 深入浅出浏览器渲染原理
- 下一篇: 第一章--第一节:环境搭建