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

Spring Boot集成内嵌MongoDB时JUnit测试失败求助

内嵌MongoDB启动报错:端口占用问题解决

在Spring Boot 2.7.10项目中使用版本2.2.0的de.flapdoodle.embed.mongo配置内嵌MongoDB,配置类代码如下:

@Configuration
public class TestMongoConfig {

    private MongodExecutable mongodExecutable;
    private MongoClient mongoClient;

    @Value("${mongo.db.host:localhost}")
    private String mongoHost;

    @Value("${mongo.db.port:27017}")
    private int mongoPort;

    @Value("${mongo.db.database:test}")
    private String mongoDatabase;

    @PostConstruct
    public void setup() throws Exception {
        MongodStarter starter = MongodStarter.getDefaultInstance();
        IMongodConfig mongodConfig = new MongodConfigBuilder()
                .version(Version.Main.V3_2)
                .net(new Net(mongoHost, mongoPort, Network.localhostIsIPv6()))
                .build();

        mongodExecutable = starter.prepare(mongodConfig);
        mongodExecutable.start();
        String connectionString = "mongodb://" + mongoHost + ":" + mongoPort;
        mongoClient = MongoClients.create(connectionString);
    }

    @PreDestroy
    public void cleanup() {
        mongodExecutable.stop();
        mongoClient.close();
    }

    @Bean
    public MongoTemplate mongoTemplate() {
        return new MongoTemplate(mongoClient, mongoDatabase);
    }
}

测试类通过@Autowired注入MongoTemplate后,部分测试失败,报错信息:

Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'testMongoConfig': Invocation of init method failed; nested exception is java.io.IOException: Could not start process: failed errno:10048 Only one usage of each socket address (protocol/network address/port) is normally permitted. for socket: 127.0.0.1:27017

2023-04-04T10:11:42.087+0530 E STORAGE [initandlisten] Failed to set up sockets during startup.

解决方案

1. 使用随机端口替代固定端口

问题根源是多测试并行执行时,同一固定端口被重复占用。修改配置让内嵌Mongo自动分配可用随机端口:

@Configuration
public class TestMongoConfig {

    private MongodExecutable mongodExecutable;
    private MongoClient mongoClient;

    @Value("${mongo.db.host:localhost}")
    private String mongoHost;

    @Value("${mongo.db.database:test}")
    private String mongoDatabase;

    @PostConstruct
    public void setup() throws Exception {
        MongodStarter starter = MongodStarter.getDefaultInstance();
        // 自动获取随机可用端口
        IMongodConfig mongodConfig = new MongodConfigBuilder()
                .version(Version.Main.V3_2)
                .net(new Net(mongoHost, Network.getFreeServerPort(), Network.localhostIsIPv6()))
                .build();

        mongodExecutable = starter.prepare(mongodConfig);
        mongodExecutable.start();
        // 获取实际分配的端口创建连接
        int actualPort = mongodConfig.net().getPort();
        String connectionString = "mongodb://" + mongoHost + ":" + actualPort;
        mongoClient = MongoClients.create(connectionString);
    }

    @PreDestroy
    public void cleanup() {
        if (mongodExecutable != null) {
            mongodExecutable.stop();
        }
        if (mongoClient != null) {
            mongoClient.close();
        }
    }

    @Bean
    public MongoTemplate mongoTemplate() {
        return new MongoTemplate(mongoClient, mongoDatabase);
    }
}

关键改动:用Network.getFreeServerPort()自动获取未被占用的端口,避免固定端口冲突。

2. 保证测试上下文隔离

如果使用JUnit 5,给测试类添加@DirtiesContext注解,确保每个测试方法执行后销毁Spring上下文,避免不同测试共享Mongo实例:

@SpringBootTest
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD)
public class YourMongoTest {
    @Autowired
    private MongoTemplate mongoTemplate;

    // 测试方法实现...
}

3. 排查外部端口占用

检查本地是否有独立的MongoDB服务正在运行,若存在会占用27017端口。可以关闭外部Mongo服务,或者临时修改配置使用其他固定端口(优先推荐随机端口方案)。

内容的提问来源于stack exchange,提问作者Yatharth Mishra

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 00:42:13