一文彻底理解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单元测试的全部内容,希望文章能够帮你解决所遇到的问题。
- 上一篇: 深入浅出浏览器渲染原理
- 下一篇: Javascript获取数组中最大和最小