JUnit5 使用者:为何 Spock 值得你看它一眼 |
您所在的位置:网站首页 › spock测试 › JUnit5 使用者:为何 Spock 值得你看它一眼 |
这篇文章的诞生纯属巧合:一是早上看到微信群中有人问 Junit 的问题(往往这个时候我就忍不住向他们推销 Spock,同样的,这次也没有忍住),二是下午读到一篇转发的 JUnit5 vs Spock 的文章。于是乎,顺应天意写了下来。 我们团队已有多年(5+ 年)的 Spock 使用经验,不仅用在 Grails 项目中,而且在几乎所有 Java 项目中同样也采用它作为测试用例的书写工具。正如我在工具推荐给出的推荐原因: Groovy DSL、jvm 下最好用的测试框架 Spock 完全担得起这样的评价!看看下面的代码示例,相信你有自己的判断。 阅读前的提醒: 本文代码主要来自于上面的文章,部分来自于我之前写的文章。并且,代码对比点也来自于那篇文章。 上面那篇文章给出了更详细对比,因为本文不是翻译,对于想了解全文内容的小伙伴请自行前往阅读。 如果你懒得读那篇文章,只想看结论,我简单归纳如下: JUnit5 名气和活跃度更大。 凡事跟写代码相关的,Spock 均胜出。 作者自己更喜欢 Spock。好了,“ talk is cheap, show me the code ”。 测试结构JUnit5 class SimpleCalculatorTest { @Test void shouldAddTwoNumbers() { //given Calculator calculator = new Calculator(); //when int result = calculator.add(1, 2); //then assertEquals(3, result); } }Spock class SimpleCalculatorSpec extends Specification { def "should add two numbers"() { given: Calculator calculator = new Calculator() when: int result = calculator.add(1, 2) then: result == 3 } } 异常测试JUnit5 @Test void shouldThrowBusinessExceptionOnCommunicationProblem() { //when Executable e = () -> client.sendPing(TEST_REQUEST_ID) //then CommunicationException thrown = assertThrows(CommunicationException.class, e); assertEquals("Communication problem when sending request with id: " + TEST_REQUEST_ID, thrown.getMessage()); assertEquals(TEST_REQUEST_ID, thrown.getRequestId()); }Spock 你没看错,Spock 的测试方法名称可以是字符串,而且在我们的实际使用过程中直接就写成中文,这样产生出来的测试报告一眼就看明白什么问题。 def "should capture exception"() { when: client.sendPing(TEST_REQUEST_ID) then: CommunicationException e = thrown() e.message == "Communication problem when sending request with id: $TEST_REQUEST_ID" e.requestId == TEST_REQUEST_ID } 有条件执行测试JUnit5 结合相应的注解来做,这里就列出几例,其余自己去查文档。 @Test @DisabledOnOs(OS.WINDOWS) void shouldTestSymlinksBasedLogic() { ... } @Test @EnabledIfSystemProperty(named = "os.arch", matches = ".*32.*") void shouldBeRunOn32BitSystems() { ... }Spock 利用 Groovy 动态语言的特性,使用“注解 + 闭包”的形式,提供更灵活的使用。 @IgnoreIf({ !jvm.java8Compatible }) def "should return empty Optional by default for unstubbed methods with Java 8+"() { ... } @Requires({ sys["targetEnvironment"] != "prod" }) def "should execute smoke testing on non production environment"() { ... } MockingJUnit5 需结合 Mockito @Test public void should_not_call_remote_service_if_found_in_cache() { //given given(cacheMock.getCachedOperator(CACHED_MOBILE_NUMBER)).willReturn(Optional.of(PLUS)); //when service.checkOperator(CACHED_MOBILE_NUMBER); //then then(webserviceMock).should(never()).checkOperator(CACHED_MOBILE_NUMBER); // verify(webserviceMock, never()).checkOperator(CACHED_MOBILE_NUMBER); //alternative syntax }Spock 内置了 Mock 机制 def "should not hit remote service if found in cache"() { given: cacheMock.getCachedOperator(CACHED_MOBILE_NUMBER) >> Optional.of(PLUS) when: service.checkOperator(CACHED_MOBILE_NUMBER) then: 0 * webserviceMock.checkOperator(CACHED_MOBILE_NUMBER) } 参数化JUnit5 @ParameterizedTest(name = "value to pay for invoice {0} should be {1}") @MethodSource("invoiceProvider") void shouldCalculateToPayValueForInvoice(Invoice invoice, BigDecimal expectedValueToPay) { //when int valueToPay = invoice.toPayValue(); //expect assertEquals(expectedValueToPay, valueToPay); } private static Stream invoiceProvider() { return Stream.of( Arguments.of(regularInvoice(), 54), Arguments.of(overduedInvoice(), 81), Arguments.of(paidInvoice(), 0) ); }Spock 这是我的最爱 @Unroll def "should sum two integers (#x + #y = #expectedResult)"() { when: int result = calculator.add(x, y) then: result == expectedResult where: x | y || expectedResult 1 | 2 || 3 -2 | 3 || 1 -1 | -2 || -3 } 并发测试因为不用 JUnit 好多年,对于 JUnit5 没有去研究是否提供了对于并发测试编写的内部支持。 这里的例子来自于我之前写的 Spock + Vert.x 自动化测试的文章。 when: BlockingVariable rowCount = new BlockingVariable() BlockingVariable callback = new BlockingVariable() pgUtils.simpleSql(NamedQuery.uncalledCallback) { rowSet -> rowCount.set(rowSet.size()) callback.set(rowSet.asList()[0].getString('callback')) } then: rowCount.get() == 1 callback.get() == 'callback2'几乎是无痛编写! Spock 对于并发测试提供了若干辅助类: BlockingVariable,这个类的作用就是一直阻塞,直到有值。它非常适合测试异步回调返回值的测试场景。 AsyncConditions,这个类用于测试异步条件是否。 PollingConditions,类似上面,但更强。 最后看完代码,你的答案是什么呢? |
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |