You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Spring Boot集成Redis(Docker部署)项目单独运行JUnit测试报NoSuchMethodError错误的排查求助

Spring Boot集成Redis(Docker部署)项目单独运行JUnit测试报NoSuchMethodError错误的排查求助

最近在折腾一个Spring Boot + Redis(Docker容器运行)的小项目,写完业务代码后加了JUnit测试,结果遇到个奇葩问题:单独运行单个测试用例必报错,但一次性跑完全部测试却啥事没有。折腾了好几个小时没头绪,来求助各位大佬🙏


一、错误详情

只有单独运行单个测试时才会触发以下错误,全量运行测试无任何问题:

Exception in thread "main" java.lang.NoSuchMethodError: 'java.lang.String org.junit.platform.engine.discovery.MethodSelector.getMethodParameterTypes()'
    at com.intellij.junit5.JUnit5TestRunnerUtil.loadMethodByReflection(JUnit5TestRunnerUtil.java:127)
    at com.intellij.junit5.JUnit5TestRunnerUtil.buildRequest(JUnit5TestRunnerUtil.java:102)
    at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:43)
    at com.intellij.rt.junit.IdeaTestRunner$Repeater$1.execute(IdeaTestRunner.java:38)
    at com.intellij.rt.execution.junit.TestsRepeater.repeat(TestsRepeater.java:11)
    at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:35)
    at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:231)
    at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:55)

二、项目相关代码片段

1. 服务层抽象测试基类

import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.junit.jupiter.MockitoExtension;
import org.mockito.junit.jupiter.MockitoSettings;
import org.mockito.quality.Strictness;

@ExtendWith(MockitoExtension.class)
@MockitoSettings(strictness = Strictness.LENIENT)
public class AbstractBaseServiceTest {

}

2. 控制层抽象测试基类

import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.webmvc.test.autoconfigure.AutoConfigureMockMvc;
import org.springframework.test.web.servlet.MockMvc;

@SpringBootTest
@AutoConfigureMockMvc
public abstract class AbstractRestControllerTest extends AbstractTestContainerConfiguration {

    @Autowired
    protected MockMvc mockMvc;

    @Autowired
    protected ObjectMapper objectMapper;

}

3. TestContainers Redis配置基类

import org.junit.jupiter.api.BeforeAll;
import org.springframework.test.context.DynamicPropertyRegistry;
import org.springframework.test.context.DynamicPropertySource;
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.junit.jupiter.Testcontainers;
import org.testcontainers.utility.DockerImageName;

@Testcontainers
public abstract class AbstractTestContainerConfiguration {

    private static final DockerImageName REDIS_IMAGE = DockerImageName.parse("redis:7.4.1");

    static final GenericContainer<?> REDIS_CONTAINER =
            new GenericContainer<>(REDIS_IMAGE).withExposedPorts(6379);

    @BeforeAll
    static void beforeAll() {
        REDIS_CONTAINER.withReuse(true);
        REDIS_CONTAINER.start();
    }

    @DynamicPropertySource
    static void overrideProps(DynamicPropertyRegistry registry) {
        registry.add("redis.host", REDIS_CONTAINER::getHost);
        registry.add("redis.port", () -> REDIS_CONTAINER.getMappedPort(6379));
    }
}

4. pom.xml核心依赖配置

<properties>
    <java.version>25</java.version>
    <junit.bom.version>5.11.4</junit.bom.version>
    <testcontainers.bom.version>1.21.4</testcontainers.bom.version>
    <mapstruct.version>1.5.5.Final</mapstruct.version>
    <lombok-mapstruct-binding.version>0.2.0</lombok-mapstruct-binding.version>
    <jacoco-version>0.8.13</jacoco-version>
    <springdoc-openapi.version>2.8.13</springdoc-openapi.version>
    <maven-surefire-plugin-version>3.5.2</maven-surefire-plugin-version>
    <maven-failsafe-plugin-version>3.5.2</maven-failsafe-plugin-version>
    <testcontainer.junit.version>1.21.4</testcontainer.junit.version>
    <redis.testcontainer.version>2.2.4</redis.testcontainer.version>
</properties>
<dependencies>

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

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

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

    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>

    <dependency>
        <groupId>org.mapstruct</groupId>
        <artifactId>mapstruct</artifactId>
        <version>${mapstruct.version}</version>
    </dependency>

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

    <dependency>
        <groupId>org.springdoc</groupId>
        <artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
        <version>${springdoc-openapi.version}</version>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-redis</artifactId>
    </dependency>

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

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-jackson2</artifactId>
    </dependency>

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

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

    <dependency>
        <groupId>org.testcontainers</groupId>
        <artifactId>junit-jupiter</artifactId>
        <version>${testcontainer.junit.version}</version>
        <scope>test</scope>
    </dependency>

    <dependency>
        <groupId>com.redis</groupId>
        <artifactId>testcontainers-redis</artifactId>
        <version>${redis.testcontainer.version}</version>
        <scope>test</scope>
    </dependency>

</dependencies>

<dependencyManagement>
    <dependencies>
        <!-- Force consistent Testcontainers set -->
        <dependency>
            <groupId>org.testcontainers</groupId>
            <artifactId>testcontainers-bom</artifactId>
            <version>${testcontainers.bom.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

三、我的排查思路(没找到问题)

  1. 一开始以为是JUnit版本冲突,毕竟NoSuchMethodError大多是类版本不匹配,但已经指定了JUnit BOM 5.11.4,Spring Boot Starter Test也应该会统一管理依赖版本,全量运行测试正常也说明依赖本身没问题?
  2. 会不会是IDEA的JUnit插件版本和项目依赖不兼容?我用的是IDEA 2024.1,暂时还没找到对应插件版本的排查方法
  3. TestContainers的配置会不会有问题?但全量运行测试时Redis容器启动正常,测试也能通过,单独运行就报错好像和它没关系?
  4. 抽象基类的注解有没有冲突?比如服务层用了MockitoExtension,控制层用了SpringBootTest,会不会单独运行时初始化顺序出问题?

有没有大佬遇到过类似的问题?麻烦帮忙看看问题出在哪,怎么解决?感激不尽🙏

火山引擎 最新活动