[spring-projects/spring-boot]从 ExpectedException 规则迁移到 AssertJ

2024-04-23 656 views
0

我们应该考虑从@ExpectedExceptionAssertJ迁移。如果/当我们升级到 JUnit 5 时这将会有所帮助。

回答

7

嗨@philwebb,我是新来的,很乐意解决这个问题。我很清楚,这个问题涉及修改所有使用@ExpectedException相应 AssertJ 替代方案的测试,对吗?也就是说,这对用户与框架交互的方式没有影响,对吗?

4

@ivange94 非常感谢您提供帮助。你是对的,这里的目的是删除我们对等价物的ExpectedException使用AssertJ

6

@snicoll 感谢您的快速回复。我正在继续开展这方面的工作。

9

当我使用./mvnw clean install构建新克隆时,测试失败

[INFO] Running org.springframework.boot.SpringApplicationTests
[ERROR] Tests run: 75, Failures: 1, Errors: 0, Skipped: 0, Time elapsed: 1,117.157 s <<< FAILURE! - in org.springframework.boot.SpringApplicationTests
[ERROR] failureResultsInSingleStackTrace(org.springframework.boot.SpringApplicationTests)  Time elapsed: 6.018 s  <<< FAILURE!
org.junit.ComparisonFailure: [Expected single stacktrace] expected:<[1]> but was:<[0]>
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at org.springframework.boot.SpringApplicationTests.failureResultsInSingleStackTrace(SpringApplicationTests.java:1168)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
    at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
    at org.springframework.boot.testsupport.rule.OutputCapture$1.evaluate(OutputCapture.java:57)
    at org.junit.rules.ExpectedException$ExpectedExceptionStatement.evaluate(ExpectedException.java:239)
    at org.junit.rules.RunRules.evaluate(RunRules.java:20)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:365)
    at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:273)
    at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:238)
    at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:159)
    at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:383)
    at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:344)

当我尝试从 IDE (InteliJ Idea) 运行测试时,我得到了

Error:java: Bad service configuration file, or exception thrown while constructing Processor object: javax.annotation.processing.Processor: Provider org.springframework.boot.configurationprocessor.ConfigurationMetadataAnnotationProcessor not found

我已经对想法错误和解决方案进行了一些研究,我发现这些错误和解决方案需要我对项目进行一些修改,所以我想我正在寻找错误的地方,因为所有这些都必须适用于其他人。

8

@ivange94 你使用什么操作系统?

6

@philwebb macOS Sierra (10.12.6)

4

@ivange94 这应该可以找到。java -version和显示什么echo $JAVA_HOME

6

java -版本显示

Ivanges-MacBook-Pro:~ ivange$ java -version
java version "1.8.0_181"
Java(TM) SE Runtime Environment (build 1.8.0_181-b13)
Java HotSpot(TM) 64-Bit Server VM (build 25.181-b13, mixed mode)

JAVA_HOME 未设置。

2

@ivange94 我有点不知所措。您可以尝试设置 aJAVA_HOME但我认为它不会解决您所看到的测试失败问题。我现在不太确定该建议什么。

0

@philwebb 没有。

2

@ivange94 真糟糕。也许您可以加入我们的 Gitter,我们可以尝试找出您的机器上发生了什么?

9

@snicoll 听起来很棒。不知道还有 gitter 频道。请问我怎样才能加入?

9

@snicoll 找到了该频道。我们将在那里继续讨论。

6

代码库中有超过一千种 ExpectedException 的用法。我是否可以在提交 PR 之前重构整个代码库,或者可以提交小型 PR?我已经完成了 spring-boot-project 中 spring-boot 子项目的重构,这已经是 66 个文件的修改,其中添加了 425 个文件,删除了 855 个文件。

我还有超过 12 个子项目需要重构。

7

感谢您查看此内容,@ivange94。在继续之前,我们应该确定要使用的语法。 AssertJ 提供两种选择:

@Test
public void testException() {
   assertThatThrownBy(() -> { throw new Exception("boom!"); }).isInstanceOf(Exception.class)
                                                             .hasMessageContaining("boom");
}
@Test
public void testException() {
   assertThatExceptionOfType(IOException.class).isThrownBy(() -> { throw new IOException("boom!"); })
                                               .withMessage("%s!", "boom")
                                               .withMessageContaining("boom")
                                               .withNoCause();
}

就第一印象而言,我认为第二个选项读起来更好。让我们看看团队其他成员的想法,以便我们能够就使用哪种方案达成一致。

3

+1 为assertThatExceptionOfType. javadoc 还说它或多或少与 相同,assertThatThrownBy但方式更自然。

3

相同的。我喜欢assertThatExceptionOfType

0

ExpectedException 有一千多种用法

我想知道我们是否可以以某种方式编写迁移脚本?也许我们可以使用 Atomist 的 AST 转换支持。

8

我还发现assertThatExceptionOfType感觉更自然,这就是我一直在使用的。

3

我想知道我们是否可以以某种方式编写迁移脚本?也许我们可以使用 Atomist 的 AST 转换支持。

@philwebb 自动化听起来很棒,但我不确定我是否确切知道 AST 转换支持的含义。 AssertJ 作者创建了一个迁移脚本,但我没有想到使用它的原因是该脚本最终可能会更改很多内容,而不仅仅是 ExpectedException。您能阐明一下您的方法吗?

3

这些文档有点简单,我还没有使用过它,但 Atomist 有一些聪明的功能,它可以根据代码结构而不是原始文本来编辑文件。 AST 代表抽象语法树,它基本上意味着您可以根据解析的文本而不是文本本身来更改内容。

我们的大多数测试看起来都是这样的:

    @Test
    public void createWhenEndpointTypeIsNullShouldThrowException() {
        this.thrown.expect(IllegalArgumentException.class);
        this.thrown.expectMessage("EndpointType must not be null");
        new ExposeExcludePropertyEndpointFilter<>(null, new MockEnvironment(), "foo");
    }

我们需要从调用中提取IllegalArgumentException.class和 ,然后将方法的其余部分设为 lambda 并以某种方式将其重新修改为:"EndpointType must not be null"this.thrown

    @Test
    public void createWhenEndpointTypeIsNullShouldThrowException() {
        assertThatExceptionOfType(IllegalArgumentException.class).isThrownBy(()-> {
            new ExposeExcludePropertyEndpointFilter<>(null, new MockEnvironment(), "foo");
        }).withMessageContaining("EndpointType must not be null");
    }
7

我是新来的,很乐意解决这个问题

@ivange94 我非常感谢您提供的帮助,但这可能是一个相当大且耗时的更改。如果您有时间,请继续调查,但ideal-for-contribution如果您想从挑战性较小的事情开始,也可以随时查看状态标签。

7

@philwebb,你是对的,这是一个耗时的改变。一遍又一遍地做同样的事情会变得无聊。我会看一下标签,但仍会继续努力。如果能让脚本正常工作,否则我会手动完成。

6

@ivange94 感谢您提供帮助,但我现在已经成功地使用搜索/替换、正则表达式、重构和纯粹的意志力的组合来迁移测试:)