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 {@Testpublic 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 {@Testpublic void testAssertNull() {assertNull("should be null", null);}@Testpublic 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:

@ContextConfiguration("/test-config.xml")
public class XmlApplicationContextTests {// class body...
}
@ContextConfiguration(classes = TestConfig.class)
public class ConfigClassApplicationContextTests {// class body...
}
复制代码

即使用@RunWith(SpringRunner.class)@ContextConfiguration,就可以起一个spring的环境并进行测试了,如下:

@RunWith(SpringRunner.class)
@ContextConfiguration(classes = CalculatorTest.TestConfig.class)
public class CalculatorTest {@Autowiredprivate ApplicationContext applicationContext;@Testpublic void application() {Assert.assertNotNull(applicationContext);Assert.assertNotNull(applicationContext.getBean("testBean"));}@Configurationpublic static class TestConfig {@Beanpublic 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进行配置:

//xml配置
<bean id="calculator" class="org.mockito.Mockito" factory-method="mock"><constructor-arg value="com.zuqiang.junit.Calculator"/>
</bean>
//test
@RunWith(SpringRunner.class)
@ContextConfiguration("/context.xml")
public class CalculatorTest {@Autowiredprivate Calculator Calculator;@Testpublic void application() {Assert.assertNotNull(Calculator);}
}复制代码

使用config class:

@RunWith(SpringRunner.class)
@ContextConfiguration(classes = CalculatorTest.MockConfig.class)
public class CalculatorTest {@Autowiredprivate Calculator calculator;@Testpublic void application() {Assert.assertNotNull(calculator);}@Configurationpublic static class MockConfig{@Beanpublic Calculator calculator() {return Mockito.mock(Calculator.class);}}
}
复制代码

mock的使用:

@RunWith(SpringRunner.class)
@ContextConfiguration(classes = CalculatorTest.MockConfig.class)
public class CalculatorTest {@Autowiredprivate Calculator calculator;@Beforepublic void before() {Mockito.when(calculator.evaluate(Mockito.anyString())).thenReturn(1);}@Testpublic void application() {Assert.assertEquals(1,calculator.evaluate("1+2"));Assert.assertEquals(1,calculator.evaluate("2+2"));}@Configurationpublic static class MockConfig {@Beanpublic Calculator calculator() {return Mockito.mock(Calculator.class);}}
}
复制代码

断言

在上面,我们已经看到了Junit提供的断言方法,对于一些简单的场景,我觉得没有什么问题。但是在一些复杂的场景下,可能会导致代码晦涩难懂。所以最后给大家介绍一个更好用的Java断言框架— AssertJ
比如下面这个比较简单的test:

    @Testpublic void test() throws Exception {//ArrangeList<String> strings = Lists.newArrayList("a","b","c");//ActString removedString = strings.remove(0);//AssertassertThat(strings, containsInAnyOrder("b", "c"));}
复制代码

用AssertJ之后的写法像下面这样:

    @Testpublic void test() throws Exception {//ArrangeList<String> strings = Lists.newArrayList("a","b","c");//ActString removedString = strings.remove(0);//AssertassertThat(strings).contains("b", "c");复制代码

一文彻底理解Java单元测试相关推荐

  1. 一文深入理解 Java 虚拟机

    类文件结构 class类文件的结构 任何一个Class文件都对应着唯一的一个类或接口的定义信息[插图],但是反过来说,类或接口并不一定都得定义在文件里(譬如类或接口也可以动态生成,直接送入类加载器中) ...

  2. 一文快速理解Java反射(详细对比图)

    反射在java中使用频率还是比较高的,比如JDK动态代理使用反射获取到目标类所有的接口列表.还有我们熟悉的JDBC获取驱动,Class.forName("com.mysql.jdbc.Dri ...

  3. 一文简单理解Java反射及使用

    目录 1 什么是反射 2 反射机制的优缺点有哪些 3 如何获取反射中的Class对象 4 Java反射API有几类 5 反射使用的步骤 6 为什么引入反射概念?反射机制的应用有哪些? 7 反射机制的原 ...

  4. 科普文丨Java 单元测试相关概念理清

    对于从业Java的小伙伴来说,"单元测试"这个词你一定不陌生,如果你想要学习 Java 单元测试,下面的内容你一定要看! 近日,实验楼上线了新课<Java 单元测试入门实战& ...

  5. 一文带你理解Java中Lock的实现原理

    转载自   一文带你理解Java中Lock的实现原理 当多个线程需要访问某个公共资源的时候,我们知道需要通过加锁来保证资源的访问不会出问题.java提供了两种方式来加锁,一种是关键字:synchron ...

  6. 一周极客热文:8张图理解Java

    图:equals()方法.hashCode()方法的区别 HashCode被设计用来提高性能.equals()方法与hashCode()方法的区别在于: 如果两个对象相等(equal),那么他们一定有 ...

  7. 一文带你理解Java中自动装箱和拆箱

    Java中自动装箱和拆箱 装箱(Boxing),也称为包装(Wrapper),是在对象中放置原语类型(primitive type)的过程,以便原语(primitive)可以作为引用对象使用. 这里的 ...

  8. 使用Mockito进行Java单元测试

    Google在3月份推出了一个关于Android MVP架构的官方Sample,除MVP架构本身之外,在这个Sample中配备了完善的单元测试用例,这对学习如何在Android中进行单元测试具有极高的 ...

  9. Mock和Java单元测试中的Mock框架Mockito介绍

    什么是Mock? 在面向对象程序设计中,模拟对象(英语:mock object,也译作模仿对象)是以可控的方式模拟真实对象行为的假的对象.程序员通常创造模拟对象(mock object)来测试其他对象 ...

最新文章

  1. c++ hook 钩子的使用介绍
  2. SEO:如何做好软文推广
  3. python实现简单的百度翻译
  4. LeetCode 1655. 分配重复整数(回溯)
  5. IoTDI2019论文列表
  6. windows史上最方便解压rar文件的软件WeDo
  7. filetype 在搜索引擎中的使用方法(2)
  8. AndroidStudio_安卓原生开发_在fragment中如何使用Toast_以及SharedPreferences---Android原生开发工作笔记149
  9. 谁设计python_如果你有设计师朋友,请对TA好一些...
  10. Linux性能测试工具
  11. 银行系统总体架构\银行核心系统\常用金融名词解释
  12. Emscripten 单词_人教版英语七年级下册单词、课文及音频汇总
  13. 小菜学前端day02(学习笔记)
  14. Worthington核心酶——木瓜蛋白酶的特征及相关应用
  15. 问卷分析之SPSS相关分析、相关系数矩阵(Pearson)
  16. 因计算机丢失d3dx9-30,Win10玩仙剑5提示“丢失d3dx9_30.dll”怎么解决?
  17. 【YoLov5实战】记录一次不太成功的实战,足球场人物识别
  18. CentOS 修改系统时区和更新时间
  19. LTE学习笔记:物理层
  20. 一个html基本写法,HTML5教程:HTML5的基础写法

热门文章

  1. 007_html头部元素
  2. linux下 发布qt程序,Linux下发布qt程序
  3. linux过滤脚本中的字段,Shell脚本中常用的文本过滤命令
  4. 通过http协议访问FTP服务器的搭建,ftp+nginx 图片服务器搭建之后使用http访问进行配置文件的修改
  5. 压缩感知 的自我理解
  6. anaconda怎么运行python程序_Heartrate:如追综心跳般实时动态可视化监测Python程序运行...
  7. mysql.info文件是什么_info 数据库
  8. 计算机多媒体技术广泛应用于各个领域,多媒体技术发展前景计算机现状及
  9. linux配置apache文件大小,linux下apache中httpd.conf文件配置参数说明
  10. gm怎么刷东西 rust_刷了这种黑板漆再也不用担心吃粉笔灰了