【问题标题】:Maven is not showing the arguments for parameterized tests, what could be wrong?Maven 没有显示参数化测试的参数,可能是什么问题?
【发布时间】:2021-01-05 22:59:51
【问题描述】:

测试似乎运行良好(有些测试失败,但它们正在运行),但日志没有显示参数,为什么?

@ExtendWith( SpringExtension.class )
@ContextConfiguration(
    locations = {
        "classpath:spring/testContext.xml",
        "classpath:applicationContext-mock.xml"
    } )
@Transactional
@ActiveProfiles( Profiles.TEST )
@Category( IntegrationTest.class )
public abstract class AbstractDalTestBase {
    @ParameterizedTest
    @ArgumentsSource(LetterSearchWithFilterAndPagingForHCPCSCodeArguments.class)
    public void letterSearchWithFilterAndPagingForHCPCSCode(String searchTerm, int expected) {
        List<?> results = findMatchingItemsWithFilterAndPaging(searchTerm, CatalogItemType.HCPCSCODE, 0, 0, null);
        int projection = loadTotalNumberOfItems(searchTerm, CatalogItemType.HCPCSCODE);
        assertThat(projection).as("projection eq results").isEqualTo(results.size());
        assertThat(projection).as("projection eq expected").isEqualTo(expected);
        assertThat(results.size()).as("results eq expected").isEqualTo(expected);
    }
class LetterSearchWithFilterAndPagingForHCPCSCodeArguments implements ArgumentsProvider {

    @Override
    public Stream<? extends Arguments> provideArguments(ExtensionContext extensionContext) {
        int count = 5643;
        return Stream.of(
            Arguments.of("A", count),
            Arguments.of("a"),
            Arguments.of("b", 2151)
        );
    }
}
[ThreadedStreamConsumer] ERROR org.apache.maven.plugin.surefire.SurefirePlugin - letterSearchWithFilterAndPagingForHCPCSCode{String, int}[1]  Time elapsed: 2.496 s  <<< FAILURE!
java.lang.AssertionError: 
[projection eq results] 
Expecting:
 <5643>
and actual:
 <5643>
to refer to the same object

我认为 junit 应该记录传递给方法的值,我怎样才能让它做到这一点?

【问题讨论】:

    标签: java maven junit junit5 maven-surefire-plugin


    【解决方案1】:

    Surefire 插件可能对此无能为力:JUnit5 似乎没有在运行/结束测试时公开测试用例参数信息,而是为特定测试提供显示名称,并且该名称包含测试运行序号和toString-ed 参数传递给测试,如[ORDINAL] ARG1, ARG2...(出现在IntelliJ IDEA JUnit runner 中的那个)。但是,Surefire 插件不会解析这些名称(无论出于何种原因,因为它们将来可能会更改?),或者在某些情况下直接忽略它们。

    这是一个示例测试(@MethodSource 似乎不影响结果):

    public final class FooTest {
    
        private static Stream<? extends Arguments> test() {
            return Stream.of(
                    Arguments.of(1, 1),
                    Arguments.of(1, 0)
            );
        }
    
        @ParameterizedTest
        @MethodSource
        public void test(final Object a, final Object b) {
            Assertions.assertEquals(a, b);
        }
    
    }
    

    上述测试失败,maven-surefire-plugin:3.0.0-M5 下的断言失败:

    [ERROR] FooTest.test(Object, Object)[2]  Time elapsed: 0.002 s  <<< FAILURE!
    org.opentest4j.AssertionFailedError: expected: <1> but was: <0>
        at FooTest.test(FooTest.java:31)
    

    我检查了当前的 3.0.6-SNAPSHOT 源代码,并应用了以下补丁(在 be236f772724aab93087c82b84ef484e2e0bfa80 之上),然后在测试 pom.xml 中将 Surefire 版本更新为 3.0.0-M6-SNAPSHOT:

    From 9b01ccc020c5c2040ef0ee6988f5faa2d179a1db Mon Sep 17 00:00:00 2001
    From: - <->
    Date: Wed, 6 Jan 2021 02:53:27 +0200
    Subject: [PATCH] Append test arguments to the method description
    
    ---
     .../maven/surefire/junitplatform/RunListenerAdapter.java     | 5 +++++
     1 file changed, 5 insertions(+)
    
    diff --git a/surefire-providers/surefire-junit-platform/src/main/java/org/apache/maven/surefire/junitplatform/RunListenerAdapter.java b/surefire-providers/surefire-junit-platform/src/main/java/org/apache/maven/surefire/junitplatform/RunListenerAdapter.java
    index b193ba5ed..8af18c110 100644
    --- a/surefire-providers/surefire-junit-platform/src/main/java/org/apache/maven/surefire/junitplatform/RunListenerAdapter.java
    +++ b/surefire-providers/surefire-junit-platform/src/main/java/org/apache/maven/surefire/junitplatform/RunListenerAdapter.java
    @@ -287,6 +287,11 @@ private StackTraceWriter toStackTraceWriter( String realClassName, String realMe
                 boolean hasLegacyDescription = description.startsWith( methodName + '(' );
                 boolean hasDisplayName = !equalDescriptions || !hasLegacyDescription;
                 String methodDesc = equalDescriptions || !hasParams ? methodSign : description;
    +            int argsPos = display.indexOf( "] " );
    +            if ( argsPos != -1 )
    +            {
    +                methodDesc += "  (" + display.substring( argsPos + 2 ) + ')';
    +            }
                 String methodDisp = hasDisplayName ? display : methodDesc;
     
                 // The behavior of methods getLegacyReportingName() and getDisplayName().
    -- 
    2.30.0
    

    然后使用mvn -Dmaven.test.skip=true clean install 将修补版本安装到我的本地存储库。现在断言失败变成了这样:

    [ERROR] FooTest.test(Object, Object)[2]  (1, 0)  Time elapsed: 0.002 s  <<< FAILURE!
    org.opentest4j.AssertionFailedError: expected: <1> but was: <0>
        at FooTest.test(FooTest.java:31)
    

    (1, 0),测试参数,现在出现在测试名称之后。

    我猜你必须在https://issues.apache.org/jira/browse/SUREFIRE 提出票证,以便维护人员可以在可能的情况下改进参数化测试名称支持(不确定是否也需要 JUnit 改进)。

    【讨论】:

    • 其实我找到了一张junit票,问题是肯定的。它固定在 3.0 M4 中(我不能使用)。如果您查看 Gradle,您会发现它在那里运行良好。明天我会更新更多细节
    • 更新了我的答案以包含所有相关细节
    【解决方案2】:

    我找到了this JUnit ticket,问题是肯定的。它在3.0.0-M5 中修复,很遗憾,我不能使用它。

    不使用显示名称的理由是它会“破坏”由 Surefire 生成的 XML 报告。因此,我们需要一种新的报告格式,而 Surefire 需要在我们报告显示名称之前采用它(参见 #373)。

    从插件版本 3.0.0-M4 开始,您可以在测试中使用细粒度的报告配置并启用短语名称和 @DisplayName。这是特定对象属性的完整列表。您不必指定例如禁用,版本和编码。如果未另行指定,布尔值将达到默认值 false。

    <build>
        <plugins>
            ...
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>3.0.0-M5</version>
                <configuration>
                    <statelessTestsetReporter implementation="org.apache.maven.plugin.surefire.extensions.junit5.JUnit5Xml30StatelessReporter">
                        <disable>false</disable>
                        <version>3.0</version>
                        <usePhrasedFileName>false</usePhrasedFileName>
                        <usePhrasedTestSuiteClassName>true</usePhrasedTestSuiteClassName>
                        <usePhrasedTestCaseClassName>true</usePhrasedTestCaseClassName>
                        <usePhrasedTestCaseMethodName>true</usePhrasedTestCaseMethodName>
                    </statelessTestsetReporter>
                    <consoleOutputReporter implementation="org.apache.maven.plugin.surefire.extensions.junit5.JUnit5ConsoleOutputReporter">
                        <disable>false</disable>
                        <encoding>UTF-8</encoding>
                        <usePhrasedFileName>false</usePhrasedFileName>
                    </consoleOutputReporter>
                    <statelessTestsetInfoReporter implementation="org.apache.maven.plugin.surefire.extensions.junit5.JUnit5StatelessTestsetInfoReporter">
                        <disable>false</disable>
                        <usePhrasedFileName>false</usePhrasedFileName>
                        <usePhrasedClassNameInRunning>true</usePhrasedClassNameInRunning>
                        <usePhrasedClassNameInTestCaseSummary>true</usePhrasedClassNameInTestCaseSummary>
                    </statelessTestsetInfoReporter>
                </configuration>
            </plugin>
        </plugins>
    </build>
    

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-11-09
    • 2020-11-15
    • 2011-06-16
    • 1970-01-01
    • 2017-09-01
    • 2012-01-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多