JUnit的@TestMethodOrder注释无法工作

31

我有一个关于下面的集成测试的问题

import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.TestMethodOrder;
import org.junit.jupiter.api.MethodOrderer.OrderAnnotation;

@SpringBootTest
@ActiveProfiles("test")
@TestMethodOrder(OrderAnnotation.class)
public class FooServiceIT {
    @Test
    @Order(1)
    void testUploadSuccess() { ... }
    @Test
    @Order(2)
    void testDownloadSuccess() { ... }
    @Test
    @Order(3)
    void testDeleteSuccess() { ... }
}

我原以为测试的执行顺序是1、2、3,但由于某些原因,实际的执行顺序却是2、3、1。

说实话,我不知道为什么注释不起作用。我使用的是Spring Boot 2.1.3和JUnit 5.4。


理论上,您应该编写测试代码以便它们可以以任何顺序运行...为什么您需要对它们进行排序呢? - Ruth
5
您的配置有误。尝试添加 @TestMethodOrder(MethodOrderer.OrderAnnotation.class),详情请参见 https://junit.org/junit5/docs/current/api/org/junit/jupiter/api/TestMethodOrder.html。 - Valijon
@Valijon 我已更新导入,我已经正确使用了OrderAnnotation类。 @RuthiRuth 这些方法正在操作远程服务器上的文件,显然,如果我不先将文件上传到服务器上,下载/删除方法将会失败(我也想保持方法分离 - 即在下载测试中不调用上传方法)。 - toucheqt
请问您能否分享您剩下的导入内容,尤其是用于 @Test 注解的导入? - Sam Brannen
订购测试的一个原因是解决这样的情况:在套件中运行单个测试成功,但运行多个测试失败,例如第二个测试因为测试工具在第一个测试后没有按预期进行拆卸。这可能很难调试,特别是在最新版本的Maven测试插件中,其中fork配置似乎有时会与junit 5非确定性地交互。 - maw
2
请使用此注释:@TestMethodOrder(MethodOrderer.OrderAnnotation.class) - Anupam Haldkar
9个回答

37

您需要正确配置您的IDE.

要求

<dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter-engine</artifactId>
    <version>5.4.0</version>
</dependency>

不要使用IDE提供的JUnit 5。如果您将其作为库添加,您将获得:

No tests found for with test runner 'JUnit 5' 
==================== and this exception ===================
TestEngine with ID 'junit-vintage' failed to discover tests
java.lang.SecurityException: class "org.junit.jupiter.api.TestMethodOrder"'s signer information does not match signer information of other classes in the same package

只需包含所提到的依赖项,您的代码将按预期工作:

import org.junit.jupiter.api.MethodOrderer;
import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestMethodOrder;

@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class FooServiceIT {

    @Test
    @Order(1)
    public void testUploadSuccess() {
        System.out.println("1");
    }

    @Test
    @Order(2)
    public void testDownloadSuccess() {
        System.out.println("2");
    }

    @Test
    @Order(3)
    public void testDeleteSuccess() {
        System.out.println("3");
    }
}

JUnit 测试结果:

1
2
3

谢谢!这不是实际的问题,但是你的答案指引了我正确的方向。问题在于我使用了junit-jupiter作为聚合依赖项,但由于某种原因,在5.4.0版本中它没有包含junit-jupiter-engine,而在5.3.2版本中有。 在我使用正确版本的依赖项后,测试根本无法运行,但是按照https://dev59.com/flQJ5IYBdhLWcg3wZlGZ#54652059建议添加平台启动器解决了问题。现在测试可以正常工作,并且它们按正确的顺序工作。 - toucheqt
1
我遇到了同样的问题。刚刚将junit-jupiter-engine版本更改为5.4.0,但仍然存在相反顺序执行的问题。您能否提供一些反馈?非常感谢。 - Deminem
只想补充一下,这个线程 https://github.com/junit-team/junit5/issues/1776 也提到了同样的问题。仍然没有运气 - 任何帮助将不胜感激。谢谢。 - Deminem
@Deminem 请确保 junit-jupiter-engine 的版本正确,不要从 IDE 中获取。如果您可以分享您的代码,我可以帮您查看。 - Valijon
@Valijon - 我刚刚确认了使用 junit-jupiter-engine 的正确版本。请自行查看。 com.personalitytest.demo:personalitytest:jar:1.0-SNAPSHOT \- org.junit.jupiter:junit-jupiter-engine:jar:5.4.0:test - Deminem
显示剩余4条评论

13

我也遇到了同样的问题。但是我找到了问题所在。我错误地导入了 "Order" 类。

错误的示例

import org.springframework.core.annotation.Order;

正确的那个

*import org.junit.jupiter.api.Order;*

另外,请使用正确的import验证以下五个类:

import org.junit.jupiter.api.Assertions;

import org.junit.jupiter.api.MethodOrderer.OrderAnnotation;

import org.junit.jupiter.api.Order;

import org.junit.jupiter.api.Test;

import org.junit.jupiter.api.TestMethodOrder;

老兄...你救了我很多时间。谢谢你。 - javalove

11

4
你的答案如何解决这个问题? - Diego Marin Santos
这就是我所缺少的东西。谢谢! - Hishara Dilshan HishD

8

如果你正在使用或曾经使用JUnit 4,请检查注释@Test的引入方式:import org.junit.Test;

对于JUnit 5,引入方式应该是:import org.junit.jupiter.api.Test;

这可能是我遇到问题的原因。


1
请确保您从 org.junit.jupiter.api 而不是 org.junit 导入库。
import org.junit.jupiter.api.MethodOrderer.OrderAnnotation;
import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestMethodOrder;

@TestMethodOrder(OrderAnnotation.class)
class OrderedTestsDemo {

    @Test
    @Order(1)
    void nullValues() {
        // perform assertions against null values
    }

    @Test
    @Order(2)
    void emptyValues() {
        // perform assertions against empty values
    }

    @Test
    @Order(3)
    void validValues() {
        // perform assertions against valid values
    }

}

代码来源:https://junit.org/junit5/docs/current/user-guide/#writing-tests-test-execution-order-methods


0

你需要正确配置你的pom.xml文件。看看我的:

<properties>
    <!-- Dependency versions -->
    <junit.jupiter.version>5.6.0</junit.jupiter.version>
    <maven-surefire-plugin.version>3.0.0-M4</maven-surefire-plugin.version>

    <!-- Java 10 -->
    <maven.compiler.source>1.10</maven.compiler.source>
    <maven.compiler.target>1.10</maven.compiler.target>

    <!-- Encoding -->
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
</properties>

<!-- Jupiter API for writing tests -->
<dependencies>
    <dependency>
        <groupId>org.junit.jupiter</groupId>
        <artifactId>junit-jupiter-engine</artifactId>
        <version>${junit.jupiter.version}</version>
        <scope>test</scope>
    </dependency>
</dependencies>

<!-- Maven Surefire plugin to run tests -->
<build>
    <plugins>
        <!-- plugin to run test cases from maven -->
        <plugin>
            <artifactId>maven-surefire-plugin</artifactId>
            <version>${maven-surefire-plugin.version}</version>
        </plugin>
        <!-- Maven plugin to use perticular java version to compile code -->
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.8.1</version>
            <configuration>
                <source>${maven.compiler.source}</source>
                <target>${maven.compiler.target}</target>
            </configuration>
        </plugin>
    </plugins>
</build>

现在您的 Junit 5 注释必须正常工作


这个解决方案已经尝试过了,但是不起作用。 - Arefe

0

在根据之前的推荐解决方案应用所有设置后,我仍然遇到相同的反向或随机@order执行问题。

Pom.xml

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.5.3.RELEASE</version>
</parent>

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>

<dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter-engine</artifactId>
    <version>5.4.0</version>
    <scope>test</scope>
</dependency>

Maven 依赖树:

mvn dependency:tree -Dverbose -Dincludes=org.junit.jupiter:junit-jupiter-engine

[INFO] com.personalitytest.demo:personalitytest:jar:1.0-SNAPSHOT
[INFO] \- org.junit.jupiter:junit-jupiter-engine:jar:5.4.0:test

JUnit测试:

@SpringBootTest
@ActiveProfiles("test")
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class JUnitOrderTest {

    private static final Logger log = LoggerFactory.getLogger(JUnitOrderTest.class);

    @Test
    @Order(1)
    public void testUploadSuccess() {
        log.info("Junit - Order 1");
    }

    @Test
    @Order(2)
    public void testDownloadSuccess() {
        log.info("Junit - Order 2");
    }

    @Test
    @Order(3)
    public void testDeleteSuccess() {
        log.info("Junit - Order 3");
    }
}

输出:

Running com.personalitytest.demo.security.JUnitOrderTest
08:48:35.470 [main] INFO com.personalitytest.demo.security.JUnitOrderTest - Junit - Order 2
08:48:35.480 [main] INFO com.personalitytest.demo.security.JUnitOrderTest - Junit - Order 3
08:48:35.481 [main] INFO com.personalitytest.demo.security.JUnitOrderTest - Junit - Order 1

@Valijon - 请看一下这段代码。任何帮助都将不胜感激 - 谢谢。 - Deminem
1
@Valijon - 在我注意到你正在使用Junit5运行测试之前,这对我来说很奇怪。@MethodExecutionOrder仅适用于Junit5,而SpringBoot版本低于2.0的任何版本都使用Junit4进行测试。因此,我从Spring设置中排除了Junit4,并安装了Jupiter(Junit5)和MockitoJupiter(Mockito5),现在一切都按预期工作。非常感谢您的帮助! - Deminem
只是想为其他人补充,@Test 注释在 Junit4 和 Junit5 中的工作方式不同。当您的 Spring Boot 配置低于 2.0 时,它会使用 Junit4,并且在通过 mvn clean test 运行测试时您并没有意识到这一点。 - Deminem

0

同样的问题。

对于我的情况,首先是@Test注释,应该是org.junit.jupiter.api.Test,而不是org.junit.Test

其次,在测试类的头部添加了@RunWith(SpringRunner.class),在我删除它后,测试用例的运行顺序符合预期。


RunWith是JUnit4的一部分,我不确定混合使用JUnit 4和5的特性是否是一个好主意。最好使用@ExtendWith(SpringExtension.class)。 - Hamza Khattabi

-3
例如,通过使用Spring Boot,您可以使用@FixMethodOrder(MethodSorters.JVM)代替@TestMethodOrder(MethodOrderer.OrderAnnotation.class)。所有测试都按照它们出现的顺序运行。
@FixMethodOrder(MethodSorters.JVM)
public class MyTest{

   @Test
   public void zzzz(){}

   @Test
   public void cccc(){}

   @Test
   public void aaaa(){}

   @Test
   public void bbbb(){}
}

订单执行流程如下:

zzzz()
cccc()
aaaa()
bbbb()

不是真的。阅读文档。“请注意,JVM的顺序可能因每次运行而异”。 - Ran
@FixMethodOrder 在 Junit4 中,而不是 Junit5! - S_intg

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接