返回介绍

3 利用 JUnit 3 和 4 进行单元测试

发布于 2025-01-04 00:44:53 字数 4516 浏览 0 评论 0 收藏 0

Groovy 简化了 JUnit 测试,使其更具有 Groovy 的特点。下面就来探讨一下 JUnit 3/4 与 Groovy 的集成情况。

3.1. JUnit 3

或者在 Groovy 类中,最显著支持 JUnit 3 测试的一个类是 GroovyTestCase 类。由于派生自 junit.framework.TestCase ,所以它提供了大量的额外方法,使 Groovy 测试变得易如反掌。

虽然 GroovyTestCase 继承自 TestCase ,但这并不意味在项目中无法使用 JUnit 4 的一些特性。实际上,最近发布的一些 Groovy 版本都带有打包的 JUnit 4,并且带有对 TestCase 的后向支持实现。在 Groovy 邮件列表中的一些对是否使用 GroovyTestCase 或 JUnit 4 的讨论中,人们认为这种选择更多是由个人口味来决定的,但利用 GroovyTestCase ,你能免费使用大量的方法,便于编写特定类型的测试。

下面就来看看 GroovyTestCase 所提供的一些方法,完整的方法列表位于 [groovy.util.GroovyTestCase] ( http://docs.groovy-lang.org/2.4.5/html/gapi/index.html?groovy/util/GroovyTestCase.html ) 的 JavaDoc 文档中。另外,不要忘记它继承自 junit.framework.TestCase ,后者继承了所有的 assert* 方法。

3.1.1 断言方法

GroovyTestCase 继承自 junit.framework.TestCase ,因此也间接继承了大量的断言方法,从而可以应用到每一个测试方法中:

class MyTestCase extends GroovyTestCase {

  void testAssertions() {
    assertTrue(1 == 1)
    assertEquals("test", "test")

    def x = "42"
    assertNotNull "x must not be null", x
    assertNull null

    assertSame x, x
  }

}

如上所示,与 Java 不同,可以在大多数场合忽略括号,从而可以使 JUnit 断言方法调用表达式实现更好的可读性。

assertScript 是一种由 GroovyTestCase 添加的有趣方法,它能保证指定的 Groovy 代码字符串成功执行,不会导致任何异常。

3.1.2 shouldFail 方法

shouldFail 用于查看指定代码块是否失败,如果失败,断言成立,否则断言失败。

void testInvalidIndexAccess1() {
  def numbers = [1,2,3,4]
  shouldFail {
    numbers.get(4)
  }
}

上例使用了基本的 shouldFail 方法接口,使用了一个 groovy.lang.Closure 做单一参数。 Closure 持有的代码被认为会在运行时中止。

如果我们要对特定 java.lang.Exception 类型进行 shouldFail 断言,我们可以使用一个 shouldFail 实现,其中第一个参数为 Exception 类,第二个参数为 Closure 类。

void testInvalidIndexAccess2() {
  def numbers = [1,2,3,4]
  shouldFail IndexOutOfBoundsException, {
    numbers.get(4)
  }
}

如果抛出 IndexOutOfBoundsException (或其后代类),则测试用例失败。

shouldFail 其实还有一个隐藏的优点:返回异常消息。如果想对异常错误消息进行断言,这一点很有用。

void testInvalidIndexAccess3() {
  def numbers = [1,2,3,4]
  def msg = shouldFail IndexOutOfBoundsException, {
    numbers.get(4)
  }
  assert msg.contains('Index: 4, Size: 4')
}
3.1.3 notYetImplemented 方法

notYetImplemented 方法受 HtmlUnit 影响很大。允许编写一个测试方法,但把它标记为还未实现。只要测试方法失败,并且被标记为 notYetImplemented ,测试就依然能够通过。

void testNotYetImplemented1() {  
  if (notYetImplemented()) return   1⃣️

  assert 1 == 2            2⃣️   
}

1⃣️ 要想使 GroovyTestCase 获取当前方法堆栈,就需要调用 notYetImplemented
2⃣️ 只要测试结果为 false ,测试执行就会成功。

可以用 @NotYetImplemented 注释来替代 notYetImplemented 方法。它能注释一个未实现方法,带有和 GroovyTestCase##notYetImplemented 相同的行为,只是不需要调用 notYetImplemented 方法。

@NotYetImplemented
void testNotYetImplemented2() {
  assert 1 == 2
}

3.2 JUnit 4

利用 Groovy 编写 JUnit 4 测试用例没有任何限制。 groovy.test.GroovyAssert 可以保存各种静态方法,它们可以用于替代 JUnit 4 测试中的 GroovyTestCase 方法。

import org.junit.Test

import static groovy.test.GroovyAssert.shouldFail

class JUnit4ExampleTests {

  @Test
  void indexOutOfBoundsAccess() {
    def numbers = [1,2,3,4]
    shouldFail {
      numbers.get(4)
    }
  }

}

如上所示, GroovyAssert 中的静态方法都在类定义之前导入进来,所以 shouldFail 可以像在 GroovyTestCase 中那样使用。

由于 groovy.test.GroovyAssert 来源自 org.junit.Assert ,所以它继承了 JUnit 所有的断言方法。但由于强力断言语句的引入,依赖断言语句成了一种良好实践,不再需要 JUnit 断言方法,而改善的消息也成为了这样做的一个主要因素。

GroovyAssert.shouldFail 并不绝对等于 GroovyTestCase.shouldFailGroovyTestCase.shouldFail 返回异常消息, GroovyAssert.shouldFail 返回异常本身,获取异常消息还需要写一些代码,但反过来说也不是没有好处,你可以访问异常的其他属性和方法:

@Test
void shouldFailReturn() {
  def e = shouldFail {
    throw new RuntimeException('foo',
                   new RuntimeException('bar'))
  }
  assert e instanceof RuntimeException
  assert e.message == 'foo'
  assert e.cause.message == 'bar'
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文