几周前,我开始创建一个小的JUnit Runner( Oleaster ),它允许您使用Jasmine方式在JUnit中编写单元测试。 我了解到,创建自定义JUnit Runners实际上非常简单。 在本文中,我想向您展示JUnit Runner在内部如何工作以及如何使用自定义Runner来修改JUnit的测试执行过程。

那么什么是JUnit Runner?

JUnit Runner是扩展JUnit抽象Runner类的类。 运行程序用于运行测试类。 可以使用@RunWith注释设置应该用于运行测试的Runner 。

@RunWith(MyTestRunner.class)
public class MyTestClass {@Testpublic void myTest() {..}
}

JUnit测试是使用JUnitCore类开始的。 可以通过从命令行运行它,也可以使用其各种run()方法之一来完成此操作(如果您按run test按钮,这就是您的IDE所做的事情)。

JUnitCore.runClasses(MyTestClass.class);

然后,JUnitCore使用反射为通过的测试类找到合适的Runner。 此处的一个步骤是在测试类上查找@RunWith批注。 如果未找到其他运行程序,则将使用默认运行程序( BlockJUnit4ClassRunner )。 将实例化Runner,并将测试类传递给Runner。 现在,实例化并运行通过的测试类是Runner的工作。

跑步者如何工作?

让我们看一下标准JUnit Runners的类层次结构:

Runner是一个非常简单的类,实现了Describable接口,并具有两个抽象方法:

public abstract class Runner implements Describable {public abstract Description getDescription();public abstract void run(RunNotifier notifier);
}

方法getDescription()从Describable继承,并且必须返回Description 。 描述包含了各种工具以后导出和使用的信息。 例如,您的IDE可能会使用此信息来显示测试结果。 run()是一种非常通用的方法, 可以运行某些内容 (例如测试类或测试套件)。 我认为通常Runner并不是您要扩展的类(它太慷慨了)。

在ParentRunner中,事情变得更加具体。 ParentRunner是具有多个子代的Runner的抽象基类。 在这里重要的是要理解,测试是按层次结构(例如树)构造和执行的。

例如:您可能运行包含其他测试套件的测试套件。 这些测试套件可能包含多个测试类。 最后,每个测试类可以包含多个测试方法。

ParentRunner具有以下三种抽象方法:

public abstract class ParentRunner<T> extends Runner implements Filterable, Sortable {    protected abstract List<T> getChildren();protected abstract Description describeChild(T child);protected abstract void runChild(T child, RunNotifier notifier);
}

子类需要在getChildren()中返回泛型T的列表。 然后,ParentRunner要求子类为每个孩子(describeChild())创建一个Description,最后运行每个孩子(runChild())。

现在,让我们看一下两个标准的ParentRunners:BlockJUnit4ClassRunner和Suite。

如果未提供其他Runner,则使用BlockJUnit4ClassRunner为默认Runner。 因此,这是运行单个测试类时通常使用的Runner。 如果您查看BlockJUnit4ClassRunner的来源,您将看到类似以下内容:

public class BlockJUnit4ClassRunner extends ParentRunner<FrameworkMethod> {@Overrideprotected List<FrameworkMethod> getChildren() {// scan test class for methonds annotated with @Test}@Overrideprotected Description describeChild(FrameworkMethod method) {// create Description based on method name}@Overrideprotected void runChild(final FrameworkMethod method, RunNotifier notifier) {if (/* method not annotated with @Ignore */) {// run methods annotated with @Before// run test method// run methods annotated with @After}}
}

当然,这被过度简化了,但是它说明了BlockJUnit4ClassRunner的基本功能。 通用类型参数FrameworkMethod基本上是java.lang.reflect.Method的包装,提供了一些方便的方法。 在getChildren()中,扫描测试类以查找使用@Test进行反射的方法。 找到的方法包装在FrameworkMethod对象中并返回。 describeChildren()从方法名称创建一个Description,然后runChild()最终运行测试方法。 BlockJUnit4ClassRunner在内部使用了很多受保护的方法。 根据您要确切执行的操作,最好检查BlockJUnit4ClassRunner中可以覆盖的方法。 您可以在GitHub上查看BlockJUnit4ClassRunner的源代码。

Suite Runner用于创建测试套件。 套件是测试(或其他套件)的集合。 一个简单的套件定义如下所示:

@RunWith(Suite.class)
@Suite.SuiteClasses({MyJUnitTestClass1.class,MyJUnitTestClass2.class,MyOtherTestSuite.class
})
public class MyTestSuite {}

通过选择带有@RunWith批注的Suite Runner来创建测试套件。 如果查看Suite的实现,您会发现它实际上非常简单。 Suite唯一要做的就是从使用@SuiteClasses批注定义的类中创建Runner实例。 因此,getChildren()返回Runners列表,runChild()将执行委托给相应的Runner。

例子

使用提供的信息,创建您自己的JUnit Runner并不难(至少我希望如此)。 如果您正在寻找一些示例自定义Runner实现,则可以查看以下列表:

  • Fabio Strozzi创建了一个非常简单明了的GuiceJUnitRunner项目 。 它使您可以选择在JUnit测试中注入Guice组件。 来源GitHub
  • Spring的SpringJUnit4ClassRunner可帮助您测试Spring框架应用程序。 它允许您在测试类中使用依赖项注入或创建事务性测试方法。 来源GitHub
  • Mockito为自动模拟初始化提供了MockitoJUnitRunner 。 来源GitHub
  • Oleaster的 Java 8茉莉花赛跑者。 源自GitHub (无耻的自我推广)

结论

JUnit Runners具有高度可定制性,可让您选择更改以完成测试执行过程。 很酷的事情是,可以更改整个测试过程,并且仍然使用IDE,构建服务器等的所有JUnit集成点。

如果您只想进行较小的更改,那么最好查看一下BlockJUnit4Class运行程序的受保护方法。 您很有可能在正确的位置找到可重写的方法。

翻译自: https://www.javacodegeeks.com/2014/08/understanding-junits-runner-architecture.html

了解JUnit的Runner架构相关推荐

  1. junit5_了解JUnit的Runner架构

    junit5 几周前,我开始创建一个小的JUnit Runner( Oleaster ),它允许您使用Jasmine方式在JUnit中编写单元测试. 我了解到,创建自定义JUnit Runners实际 ...

  2. junit runner_了解JUnit的Runner架构

    junit runner 几周前,我开始创建一个小的JUnit Runner( Oleaster ),它允许您使用Jasmine方式在JUnit中编写单元测试. 我了解到,创建自定义JUnit Run ...

  3. 【Cucumber系列】Junit Test Runner和CucumberOptions

    目录 新建Junit Runner类 执行测试 新建Junit Runner类 参考代码 import io.cucumber.junit.Cucumber; import io.cucumber.j ...

  4. 深入JUnit源码之Runner

    初次用文字的方式记录读源码的过程,不知道怎么写,感觉有点贴代码的嫌疑.不过中间还是加入了一些自己的理解和心得,希望以后能够慢慢的改进,感兴趣的童鞋凑合着看吧,感觉JUnit这个框架还是值得看的,里面有 ...

  5. JUnit 5 – 早期试用体验 – 第2篇

    \ 主要结论 \\ JUnit 5就要来了!\\t 其中包含改进的API和扩展模型将大幅完善"JUnit工具".\\t 模块化的体系结构使得"JUnit平台"可 ...

  6. 关于JUnit5 你必须知道的(二)JUnit 5的新特性

    之前介绍了下JUnit 5的架构和如何在maven下运行JUnit 5测试.这篇博客主要介绍下JUnit 5的新特性. 包可见性 常用注解 测试命名 断言 tag标记 扩展机制 包可见性 在JUnit ...

  7. 「译」JUnit 5 系列:环境搭建

    原文地址:http://blog.codefx.org/libraries/junit-5-setup/ 原文日期:15, Feb, 2016 译文首发:Linesh 的博客:环境搭建 我的 Gith ...

  8. 栋的月结 | 第二回合(定期更新、动态、架构、云技术、算法、后端、前端、收听/收看、英文、书籍、影视、好歌、新奇)[含泪总结.. 憋泪分享!]

    开篇词 大家好!以下是我在 2020 年 2 月 1 日至 29 日的所见.所闻.所学和所悟. 现在,我把它们安利给你们. 定期更新 原创专栏: 一文搞定 Linux 管理员手册:既简单又深刻 官方授 ...

  9. JUnit 5 简介

    转自:https://www.ibm.com/developerworks/cn/java/j-introducing-junit5-part1-jupiter-api/index.html http ...

最新文章

  1. 都啥时候了,你还怕学了Python找不到工作?
  2. 人工智能+能源:能源行业变革新趋势
  3. Winform无法加载基类的错误解决
  4. 我眼中的移动互联网(多原创视频)
  5. clickhouse大数据分析技术与实战_从销售到经营——大客户销售策略与实战技术...
  6. 论文浅尝 | 面向单关系事实问题的中文问答模型
  7. Android NDK学习(二):编译脚本语法Android.mk和Application.mk
  8. 大一java题库及答案_2016最新java考试题库及答案
  9. ecshop源码分析-ecshop二次开发
  10. 随身WiFi改装天线折腾日记
  11. html颜色转换rgba,RGB颜色在线转换
  12. 任玉刚:让你的职业迷茫从哪来回哪去
  13. Scarlett~スカーレット 有感,新的价值观
  14. 如何给linux预装一些工具,linux 下的一些基本工具的使用方法
  15. 模拟信号与数字信号的本质区别
  16. OpenSSL Cipher 加密解密 Ruby on Rails
  17. 功不唐捐—— 程序员职场第一课 后记
  18. 微信开发之微信环境h5页面登录实现流程
  19. cocoscreator getSpriteFrame is not a function 问题
  20. 软件测试|缺陷的生命周期是怎么样的

热门文章

  1. SpringSecurity认证
  2. getSerializableExtra
  3. vba mysql update多字段_vba操作Mysql使用UPDATE一次更新多组数据
  4. mysql 密码hash算法_如何用hash创建一个mySQL用户(‘sha256’,$salt.$password)?
  5. (转)Spring Boot通过ImportBeanDefinitionRegistrar动态注入Bean
  6. lambda表达式语法_使用类似Lambda的语法作为Java中的表达式进行切换
  7. layui绑定json_JSON绑定:概述系列
  8. git log 迁移_现场故事:从Log4J迁移到Log4J2
  9. java 枚举内嵌枚举_高度有用的Java ChronoUnit枚举
  10. java分布式系统开发_从微服务到分布式系统-Java开发人员生存指南