您的位置:软件测试 > 开源软件测试 > 开源单元测试工具 > junit
JUnit 5系列之基础入门介绍
作者:Linesh 发布时间:[ 2016/9/29 14:32:34 ] 推荐标签:单元测试 Junit

  还有 assertAll 方法,它接受可变数量的断言作为参数,并保证它们全部得到执行,然后再把错误信息(如果有)一并汇报出来。
  @Test
  void assertAllProperties() {
  Address address = new Address("New City", "Some Street", "No");
  assertAll("address",
  () -> assertEquals("Neustadt", address.city),
  () -> assertEquals("Irgendeinestra?e", address.street),
  () -> assertEquals("Nr", address.number)
  );
  }
  org.opentest4j.MultipleFailuresError: address (3 failures)
  expected: <Neustadt> but was: <New City>
  expected: <Irgendeinestra?e> but was: <Some Street>
  expected: <Nr> but was: <No>
  这个特性在检查对象的多个属性值时非常有用。按照一般的做法,测试在第一个断言失败时会挂掉了,此时只有第一个出错的地方得到提示,而你无法得知其他值的断言是否成功,只好再跑一遍测试。
  后,我们终于有了 assertThrows 和 expectThrows 方法。两者均会在被测方法未抛出预期异常时失败。而后者还会返回抛出的异常实例,以用于后续的验证,比如,断言异常信息包含正确的信息等。
  @Test
  void assertExceptions() {
  assertThrows(Exception.class, this::throwing);
  Exception exception = expectThrows(Exception.class, this::throwing);
  assertEquals("Because I can!", exception.getMessage());
  }
  假言/判定(Assumptions)
  假言/判定允许你仅在特定条件满足时才运行测试。这个特性能够减少测试组件的运行时间和代码重复,特别是在假言都不满足的情况下。
@Test
void exitIfFalseIsTrue() {
assumeTrue(false);
System.exit(1);
}
@Test
void exitIfTrueIsFalse() {
assumeFalse(this::truism);
System.exit(1);
}
private boolean truism() {
return true;
}
@Test
void exitIfNullEqualsString() {
assumingThat(
"null".equals(null),
() -> System.exit(1)
);
}
  假言/判定适用于两种情形,要么是你希望在某些条件不满足时中止测试,要么是你希望仅当某个条件满足时才执行(部分)测试。主要的区别是,被中止的测试是以被禁用(disabled)的形式被报告,此时没有测试任何内容,因为条件得不到满足。
  测试嵌套
  在 JUnit 5 中,嵌套测试几乎不费吹灰之力。你只需要在嵌套的类上添加 @Nested 注解,类中的所有方法即会被引擎执行:
package org.codefx.demo.junit5;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
class Nest {
int count = Integer.MIN_VALUE;
@BeforeEach
void setCountToZero() {
count = 0;
}
@Test
void countIsZero() {
assertEquals(0, count);
}
@Nested
class CountGreaterZero {
@BeforeEach
void increaseCount() {
count++;
}
@Test
void countIsGreaterZero() {
assertTrue(count > 0);
}
@Nested
class CountMuchGreaterZero {
@BeforeEach
void increaseCount() {
count += Integer.MAX_VALUE / 2;
}
@Test
void countIsLarge() {
assertTrue(count > Integer.MAX_VALUE / 2);
}
}
}
}
  如你所见,嵌套类中的 @BeforeEach(及 @AfterEach )注解也工作良好。不过,构造顺序似乎还未被写入文档,它们的初始化次序是从外向内的。这也让你能叠加式地为内部类准备测试数据。
  如果嵌套的内部测试想要存取外部测试类的字段,那么嵌套类本身不应该是静态的。但这样一来也禁止了静态方法的使用,因而这种场景下@BeforeAll 和 @AfterAll 方法也无法使用了(还是说终有他法实现?)
  你可能有疑惑,嵌套的内部测试类有什么用。个人而言,我用内部类来渐进测试接口,其他人则多用于保持测试类短小专注。后者同时也有一个经典的例子来说明,例子由 JUnit 团队提供,它测试了一个栈:
class TestingAStack {
Stack<Object> stack;
boolean isRun = false;
@Test
void isInstantiatedWithNew() {
new Stack<Object>();
}
@Nested
class WhenNew {
@BeforeEach
void init() {
stack = new Stack<Object>();
}
// some tests on 'stack', which is empty
@Nested
class AfterPushing {
String anElement = "an element";
@BeforeEach
void init() {
stack.push(anElement);
}
// some tests on 'stack', which has one element...
}
}
}
  在上面的例子中,栈的状态改变会反映到内层的测试类中,其中内部类又基于自身的场景执行了一些测试。
  测试命名
  JUnit 5 提供了一个注解 @DisplayName,它用以为开发者提供更可读的测试类和测试方法信息。
  上面的 stack 测试例子加上该注解以后变成这样:
@DisplayName("A stack")
class TestingAStack {
@Test
@DisplayName("is instantiated with new Stack()")
void isInstantiatedWithNew() { /*...*/ }
@Nested
@DisplayName("when new")
class WhenNew {
@Test
@DisplayName("is empty")
void isEmpty() { /*...*/ }
@Test
@DisplayName("throws EmptyStackException when popped")
void throwsExceptionWhenPopped() { /*...*/ }
@Test
@DisplayName("throws EmptyStackException when peeked")
void throwsExceptionWhenPeeked() { /*...*/ }
@Nested
@DisplayName("after pushing an element")
class AfterPushing {
@Test
@DisplayName("it is no longer empty")
void isEmpty() { /*...*/ }
@Test
@DisplayName("returns the element when popped and is empty")
void returnElementWhenPopped() { /*...*/ }
@Test
@DisplayName(
"returns the element when peeked but remains not empty")
void returnElementWhenPeeked(){ /*...*/ }
}
}
}
  这是一份TDDer 看了会感动,BDDer 看了会流泪的测试结果输出。

  回顾
  差不多这些了,恭喜你终于读完了。我们匆匆过完了 JUnit 5 的基本特性,现在,你应该了解了所有写测试的必备知识了:包括如何为方法添加生命周期注解(@[Before|After][All|Each]、如何注解测试方法本身(@Test)、如何嵌套测试(@Nested)、如何给测试一个好信息(@DisplayName),你也应该能了解断言和假言判定是如何工作的了(基本上与前版无异)。
  不过这可还没完!我们还没聊到 测试方法的条件执行,没聊到非常酷的 参数注入 ,以及 JUnit 5 的扩展机制 和 架构体系 呢。放心,这真的是后了,这些话题我们会一个月后再聊,现在你可以先休息一下啦。

上一页12下一页
软件测试工具 | 联系我们 | 投诉建议 | 诚聘英才 | 申请使用列表 | 网站地图
沪ICP备07036474 2003-2017 版权所有 上海泽众软件科技有限公司 Shanghai ZeZhong Software Co.,Ltd