如何使 junit 测试在 springboot 应用程序中使用嵌入式 mongoDB?

Posted

技术标签:

【中文标题】如何使 junit 测试在 springboot 应用程序中使用嵌入式 mongoDB?【英文标题】:How to make the junit tests use the embedded mongoDB in a springboot application? 【发布时间】:2018-06-10 21:36:32 【问题描述】:

我正在学习 springboot 并创建了一个简单的 springboot 应用程序。我希望它在运行单元测试时使用嵌入式 mongoDB,而在应用程序的其余部分运行外部 mongoDB。但是,它使用外部 mongoDB 进行单元测试,而不是嵌入式的。 我的 POM 中有以下两个依赖项。

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-mongodb</artifactId>
    </dependency>
    <dependency>
        <groupId>de.flapdoodle.embed</groupId>
        <artifactId>de.flapdoodle.embed.mongo</artifactId>
        <scope>test</scope>
    </dependency>

我的属性文件有以下内容:

# MongoDB properties
mongo.db.name=person_testDB
mongo.db.url=localhost

#external Mongo url
spring.data.mongodb.uri=mongodb://localhost:27017/personDB

我有一个包含嵌入式 MongoDB 配置的配置文件 (MongoDBConfig.java):

@EnableMongoRepositories
public class MongoDBConfig 

@Value("$mongo.db.url")
private String MONGO_DB_URL;

@Value("$mongo.db.name")
private String MONGO_DB_NAME;

@Bean
public MongoTemplate mongoTemplate() 
    MongoClient mongoClient = new MongoClient(MONGO_DB_URL);
    MongoTemplate mongoTemplate = new MongoTemplate(mongoClient, MONGO_DB_NAME);
    return mongoTemplate;
 

以下是我的PersonService.java类:

@Service
public class PersonService  
private static final Logger logger = LoggerFactory.getLogger(PersonService.class);      
@Autowired
MongoTemplate mongoTemplate;            
public void savePerson(Person person) 
    String name = person.getName();
    String collectionName = name.substring(0, 1);
        mongoTemplate.save(person, collectionName);
                   

我对 PersonsService 类的单元测试如下:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = MongoDBConfig.class)
@SpringBootTest(classes = PersonService.class)
@DataMongoTest
public class PersonServiceTest 

@Autowired
PersonService personService;    
MongodForTestsFactory factory;
MongoClient mongo;

@Before
public void setup() throws Exception 
    factory = MongodForTestsFactory.with(Version.Main.PRODUCTION);
    mongo = factory.newMongo();


@After
public void teardown() throws Exception 
    if (factory != null)
        factory.shutdown();


@Test
public void testSave()
Person person = new Person("Bob Smith " , 25);
personService.savePerson(person);


它在外部 MongoDB 中正确创建集合名称和文档名称,这不是我想要的。如何将 unitTests 限制为嵌入式 Mongo?

【问题讨论】:

How do you configure Embedded MongDB for integration testing in a Spring Boot application?的可能重复 【参考方案1】:

另一种方法是在测试中运行整个 Spring Boot 应用程序。在这种情况下,您的 Spring Boot 应用程序将被自动发现并由 Spring Boot 下载并启动嵌入式 mongoDB

@RunWith(SpringRunner.class)
@SpringBootTest
public class YourSpringBootApplicationTests 

08:12:14.676 INFO EmbeddedMongo:42 - 注意:noprealloc 可能会受到伤害 许多应用程序中的性能 08:12:14.694 INFO EmbeddedMongo:42 - 2017-12-31T08:12:14.693+0200 我控制 [initandlisten] MongoDB 开始: pid=2246 端口=52299 08:12:22.005 信息连接:71 - 打开连接 [connectionIdlocalValue:2, serverValue:2] 到 本地主机:52299

在您的示例中,您可以修改代码以便在不同的端口上启动嵌入式 Mongo:

    添加 test/resoures/test.properties 文件以覆盖 application.properties 中的属性

    mongo.db.name=person_testDB
    mongo.db.url=localhost
    mongo.db.port=12345
    

    修改 MongoDBConfig:添加 MONGO_DB_PORT 字段

    @EnableMongoRepositories
    public class MongoDBConfig 
        @Value("$mongo.db.url")
        private String MONGO_DB_URL;
    
        @Value(("$mongo.db.port:27017"))
        private int MONGO_DB_PORT;
    
        @Value("$mongo.db.name")
        private String MONGO_DB_NAME;
    
        @Bean
        public MongoTemplate mongoTemplate() 
            MongoClient mongoClient = new MongoClient(MONGO_DB_URL, MONGO_DB_PORT);
            MongoTemplate mongoTemplate = new MongoTemplate(mongoClient, MONGO_DB_NAME);
            return mongoTemplate;
        
    
    

    修改测试类: 删除 @DataMongoTest 注释。此注释强制启动嵌入式 mongoDB 实例

    static MongodExecutable mongodExecutable;
    
    @BeforeClass
    public static void setup() throws Exception 
        MongodStarter starter = MongodStarter.getDefaultInstance();
        String bindIp = "localhost";
        int port = 12345;
        IMongodConfig mongodConfig = new MongodConfigBuilder()
                .version(Version.Main.PRODUCTION)
                .net(new Net(bindIp, port, Network.localhostIsIPv6()))
                .build();
        mongodExecutable = null;
        try 
            mongodExecutable = starter.prepare(mongodConfig);
            mongodExecutable.start();
         catch (Exception e)
            // log exception here
            if (mongodExecutable != null)
                mongodExecutable.stop();
        
    
    
    @AfterClass
    public static void teardown() throws Exception 
        if (mongodExecutable != null)
            mongodExecutable.stop();
    
    

另一种方法是使用 MongoRepository 并初始化嵌入的 Mongo 作为测试 @Configuration 类的一部分:此处概述:How do you configure Embedded MongDB for integration testing in a Spring Boot application?

【讨论】:

以上是关于如何使 junit 测试在 springboot 应用程序中使用嵌入式 mongoDB?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 SpringBoot2、JUnit5 和 Kotlin 将配置属性注入单元测试

如何使 JUnit 测试用例按顺序运行?

(15)SpringBoot使用Junit单元测试

springboot+junit4单元测试如何使用?

如何在多模块项目中使用 JUnit5 和 SpringBoot2 通过 gradle 而不是 intelliJ 运行测试

如何使用springboot编写rest控制器、服务和dao层的junit测试用例?