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