我有一个相当简单的Spring Boot应用程序,它公开了一个小的REST API并从MongoDB实例中检索数据。对MongoDB实例的查询通过基于Spring Data的存储库进行。下面是一些关键代码。
// Main application class @EnableAutoConfiguration(exclude={MongoAutoConfiguration.class, MongoDataAutoConfiguration.class}) @ComponentScan @Import(MongoConfig.class) public class ProductApplication { public static void main(String[] args) { SpringApplication.run(ProductApplication.class, args); } } // Product repository with Spring data public interface ProductRepository extends MongoRepository<Product, String> { Page<Product> findAll(Pageable pageable); Optional<Product> findByLineNumber(String lineNumber); } // Configuration for "live" connections @Configuration public class MongoConfig { @Value("${product.mongo.host}") private String mongoHost; @Value("${product.mongo.port}") private String mongoPort; @Value("${product.mongo.database}") private String mongoDatabase; @Bean(name="mongoClient") public MongoClient mongoClient() throws IOException { return new MongoClient(mongoHost, Integer.parseInt(mongoPort)); } @Autowired @Bean(name="mongoDbFactory") public MongoDbFactory mongoDbFactory(MongoClient mongoClient) { return new SimpleMongoDbFactory(mongoClient, mongoDatabase); } @Autowired @Bean(name="mongoTemplate") public MongoTemplate mongoTemplate(MongoClient mongoClient) { return new MongoTemplate(mongoClient, mongoDatabase); } } @Configuration @EnableMongoRepositories public class EmbeddedMongoConfig { private static final String DB_NAME = "integrationTest"; private static final int DB_PORT = 12345; private static final String DB_HOST = "localhost"; private static final String DB_COLLECTION = "products"; private MongodExecutable mongodExecutable = null; @Bean(name="mongoClient") public MongoClient mongoClient() throws IOException { // Lots of calls here to de.flapdoodle.embed.mongo code base to // create an embedded db and insert some JSON data } @Autowired @Bean(name="mongoDbFactory") public MongoDbFactory mongoDbFactory(MongoClient mongoClient) { return new SimpleMongoDbFactory(mongoClient, DB_NAME); } @Autowired @Bean(name="mongoTemplate") public MongoTemplate mongoTemplate(MongoClient mongoClient) { return new MongoTemplate(mongoClient, DB_NAME); } @PreDestroy public void shutdownEmbeddedMongoDB() { if (this.mongodExecutable != null) { this.mongodExecutable.stop(); } } } @RunWith(SpringJUnit4ClassRunner.class) @SpringApplicationConfiguration(classes = TestProductApplication.class) @IntegrationTest @WebAppConfiguration public class WtrProductApplicationTests { @Test public void contextLoads() { // Tests empty for now } } @EnableAutoConfiguration(exclude={MongoAutoConfiguration.class, MongoDataAutoConfiguration.class}) @ComponentScan @Import(EmbeddedMongoConfig.class) public class TestProductApplication { public static void main(String[] args) { SpringApplication.run(TestProductApplication.class, args); } }
因此,这里的想法是使集成测试(目前为空)连接到嵌入式mongo实例,而不是“实时”实例。但是,它不起作用。我可以看到测试连接到Mongo的“实时”实例,并且如果我关闭测试,则构建将失败,因为它仍在尝试连接到Mongo的实时实例。有人知道为什么吗?如何获得测试以连接到嵌入式实例?
如果由于任何原因无法使用它,请继续阅读。
测试类别:
@RunWith(SpringJUnit4ClassRunner.class) @SpringApplicationConfiguration(classes = { Application.class, TestMongoConfig.class // <--- Don't forget THIS }) public class GameRepositoryTest { @Autowired private GameRepository gameRepository; @Test public void shouldCreateGame() { Game game = new Game(null, "Far Cry 3"); Game gameCreated = gameRepository.save(game); assertEquals(gameCreated.getGameId(), gameCreated.getGameId()); assertEquals(game.getName(), gameCreated.getName()); } }
简单的MongoDB存储库:
public interface GameRepository extends MongoRepository<Game, String> { Game findByName(String name); }
MongoDB测试配置:
import com.mongodb.Mongo; import com.mongodb.MongoClientOptions; import de.flapdoodle.embed.mongo.MongodExecutable; import de.flapdoodle.embed.mongo.MongodProcess; import de.flapdoodle.embed.mongo.MongodStarter; import de.flapdoodle.embed.mongo.config.IMongodConfig; import de.flapdoodle.embed.mongo.config.MongodConfigBuilder; import de.flapdoodle.embed.mongo.config.Net; import de.flapdoodle.embed.mongo.distribution.Version; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.mongo.MongoProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import java.io.IOException; @Configuration public class TestMongoConfig { @Autowired private MongoProperties properties; @Autowired(required = false) private MongoClientOptions options; @Bean(destroyMethod = "close") public Mongo mongo(MongodProcess mongodProcess) throws IOException { Net net = mongodProcess.getConfig().net(); properties.setHost(net.getServerAddress().getHostName()); properties.setPort(net.getPort()); return properties.createMongoClient(this.options); } @Bean(destroyMethod = "stop") public MongodProcess mongodProcess(MongodExecutable mongodExecutable) throws IOException { return mongodExecutable.start(); } @Bean(destroyMethod = "stop") public MongodExecutable mongodExecutable(MongodStarter mongodStarter, IMongodConfig iMongodConfig) throws IOException { return mongodStarter.prepare(iMongodConfig); } @Bean public IMongodConfig mongodConfig() throws IOException { return new MongodConfigBuilder().version(Version.Main.PRODUCTION).build(); } @Bean public MongodStarter mongodStarter() { return MongodStarter.getDefaultInstance(); } }
pom.xml
<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> <version>1.48.0</version> <scope>test</scope> </dependency>