You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何解决Maven测试模块与公共模块的循环依赖问题

解决Maven循环依赖问题:测试Mock模块与公共模块的依赖冲突

项目结构

project:
├── pom.xml
│ 
├── project-algo-common
│   ├── pom.xml
│   └── src.main.java
│                  └── com.company.project
│                                     ├──── providers
│                                     │          ├──── ProviderX.java
│                                     │          ├──── ProviderY.java
│                                     │          └──── ProviderZ.java
│                                     └──── entities
│                                                ├──── X.java
│                                                ├──── Y.java
│                                                └──── Z.java
│
├── project-algo-A1
│   ├── pom.xml
│   ├── src.main.java
│   │              └── com.company.project
│   │                                 ├──── helpers
│   │                                 │          ├──── HelperPPP.java
│   │                                 │          ├──── HelperOOO.java
│   │                                 │          └──── HelperKKK.java
│   │                                 └──── computator
│   │                                            └──── ComputatorA1.java
│   └── src.test.java
│                  └── com.company.project
│                                     └──── computator
│                                                └──── ComputatorA1Test.java
│
└── project-algo-B1
    ├── pom.xml
    ├── src.main.java
    │              └── com.company.project
    │                                 ├──── helpers
    │                                 │          ├──── HelperQQQ.java
    │                                 │          ├──── HelperWWW.java
    │                                 │          └──── HelperEEE.java
    │                                 └──── computator
    │                                            └──── ComputatorB1.java
    └── src.test.java
                   └── com.company.project
                                      └──── computator
                                                 └──── ComputatorB1Test.java

问题场景与报错

项目中Helper类依赖project-algo-common模块的Provider类从MongoDB获取数据,单元测试时需要Mock这些Provider类,改为从CSV文件读取数据。为此创建了ProviderXMocked、ProviderYMocked、ProviderZMocked类,计划放到project-algo-unit-test模块中,作为project-algo-common的test scope依赖。但该测试模块本身需要依赖project-algo-common的主代码,导致循环依赖,报错如下:

[ERROR] The projects in the reactor contain a cyclic reference: Edge between 'Vertex{label='com.company.project:project-algo-unit-test:3.0.0-SNAPSHOT'}' and 'Vertex{label='com.company.project:project-algo-common:3.0.0-SNAPSHOT'}' introduces to cycle in the graph com.company.project:project-algo-common:3.0.0-SNAPSHOT --> com.company.project:project-algo-unit-test:3.0.0-SNAPSHOT --> com.company.project:project-algo-common:3.0.0-SNAPSHOT

解决方案

方案1:将Mock类直接放入公共模块的测试源码目录

  • 无需单独创建project-algo-unit-test模块,直接在project-algo-common的src/test/java下新建com.company.project.providers.mock包,将所有Mock类放在这里。
  • 优势:彻底消除循环依赖,结构简洁,Mock类与原Provider类在同一模块的测试代码中,逻辑关联紧密。
  • 注意:如果其他业务模块(如A1、B1)需要复用这些Mock类,可以通过project-algo-common的test jar引入,需要在common模块的pom.xml中配置maven-jar-plugin打包测试代码:
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-jar-plugin</artifactId>
    <executions>
        <execution>
            <goals>
                <goal>test-jar</goal>
            </goals>
        </execution>
    </executions>
</plugin>

其他模块依赖时使用:

<dependency>
    <groupId>com.company.project</groupId>
    <artifactId>project-algo-common</artifactId>
    <version>3.0.0-SNAPSHOT</version>
    <type>test-jar</type>
    <scope>test</scope>
</dependency>

方案2:调整依赖关系,让测试模块仅被业务模块依赖

  • 重构依赖方向:不让project-algo-common依赖project-algo-unit-test,而是让业务模块(A1、B1)的test scope依赖project-algo-unit-test,同时project-algo-unit-test依赖project-algo-common的主代码(或test jar)。
  • 具体步骤:
    1. 在project-algo-unit-test的pom.xml中添加对project-algo-common的compile或test scope依赖。
    2. 在project-algo-A1和project-algo-B1的pom.xml中,添加对project-algo-unit-test的test scope依赖。
  • 优势:避免循环依赖,测试模块职责明确,仅为业务模块的测试提供Mock类支持。

方案3:使用Mock框架动态生成Mock实例,无需硬编码Mock类

  • 改用Mockito等Mock框架,直接在测试代码中动态Mock Provider类,无需编写ProviderXMocked这类硬编码的Mock类。
  • 示例代码:
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import static org.mockito.Mockito.when;
import java.util.List;

public class HelperPPPTTest {
    @Mock
    private ProviderX providerX;

    private HelperPPP helperPPP;

    @BeforeEach
    void setUp() {
        MockitoAnnotations.openMocks(this);
        // 从CSV读取测试数据
        List<X> mockData = CsvReader.read("x_test_data.csv");
        // 设置Mock方法的返回值
        when(providerX.fetchData()).thenReturn(mockData);
        helperPPP = new HelperPPP(providerX);
    }

    @Test
    void testHelperLogic() {
        // 执行测试逻辑验证
        ...
    }
}
  • 优势:无需维护独立的Mock类,减少代码量,彻底避免模块依赖问题,同时Mock逻辑更灵活,支持多场景测试。

内容的提问来源于stack exchange,提问作者Paul Marcelin Bejan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 22:12:51