1

我正在使用 Spring-Boot 项目和 MongoRepository 而不是 MongoTemplate。

使用 MongoTemplate 时,可以使用 MongoConnectionPool 动态设置主机名,如下所示:

@Autowired
MongoConnectionPool mongoConn
....
mongoConn.setHostname("127.23.45.89");
mongoConn.setPort(27017);

如何使用 MongoRepository 达到相同的效果?

我知道我可以通过指定主机名和端口

spring.data.mongodb.host=hostname1
spring.data.mongodb.port=27017

在 application.properties 文件中。

但是我正在使用 GenericContainer 通过 Docker 容器启动一个 mongo 实例来运行我的单元测试。容器将 IP 地址和端口动态分配给 mongo 实例,因此我需要能够在运行时动态设置 MongoRepository 的主机名和端口。

这就是我设置单元测试的方式。

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = MongoConfiguration.class)
public class HierarchiesServiceImplTests {
private static final Logger log = LoggerFactory.getLogger(HierarchiesServiceImplTests.class);

@Autowired
private HierarchiesService hierarchiesService;

@Autowired
private HierarchyRepository hierarchyRepo;

@BeforeClass
public void setUp() {
    MockitoAnnotations.initMocks(this);

    startMongo();
}

/**
 * Starts a Mongo docker container, and configures the repository factory to use this instance.
 */
private void startMongo() {
    GenericContainer mongo = new GenericContainer("mongo:3")
            .withExposedPorts(27017);
    mongo.start();

    String containerIpAddress = mongo.getContainerIpAddress();
    int mappedPort = mongo.getMappedPort(27017);

    //TODO: set the hostname and port here so that the MongoRepository use this mongo instance instead of the default localhost.

    log.info("Container mongo:3 listening on {}:{}", containerIpAddress, mappedPort);
}

这就是我的 MongoConfiguration.class

@Configuration
@EnableMongoRepositories
@ComponentScan({"com.is.hierarchies.service"})
public class MongoConfiguration {

}
4

3 回答 3

1

容器将 IP 地址和端口动态分配给 mongo 实例,因此我需要能够在运行时动态设置 MongoRepository 的主机名和端口。

您还可以在启动时覆盖属性:

$ java -jar YourApp.jar --spring.data.mongodb.host=hostnamexyz --spring.data.mongodb.port=123

或者

$ java -Dspring.data.mongodb.host=hostnamexyz -Dspring.data.mongodb.port=123 -jar YourApp.jar

或通过 Docker:

$ docker run -e spring.data.mongodb.host=hostnamexyz -e spring.data.mongodb.port=123 -p 8080:8080 -i -t yourdocker:latest

我只用 one 测试了 docker 命令-e param,但我不明白为什么我们不能提供多个!

于 2016-09-06T21:09:51.027 回答
0

用你的覆盖 MongoTemplate Bean

你可以在这个测试中定义一个额外的@Configuration类,只是为了覆盖MongoTemplate.

MongoRepository使用 aMongoTemplate执行其操作,因此通过定义 a @Bean MongoTemplate,我们可以设置我们选择的连接详细信息。这就是Repository将要使用的东西。

完整代码:

RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = MongoConfiguration.class)
public class HierarchiesServiceImplTests {
private static final Logger log = LoggerFactory.getLogger(HierarchiesServiceImplTests.class);

private static String containerIpAddress;
private static int mappedPort;

@Autowired
private HierarchiesService hierarchiesService;

@Autowired
private HierarchyRepository hierarchyRepo;

/**
 * Starts a Mongo docker container, and configures the repository factory to use this instance.
 */
private void startMongo() {
    GenericContainer mongo = new GenericContainer("mongo:3").withExposedPorts(27017);
    mongo.start();

    containerIpAddress = mongo.getContainerIpAddress();
    mappedPort = mongo.getMappedPort(27017);

    log.info("Container mongo:3 listening on {}:{}", containerIpAddress, mappedPort);
}

@Configuration
public static class MongoTestConfiguration {    
    @Bean
    @Primary
    public MongoTemplate  mongoTemplate() throws DataAccessException, Exception{
        return createMongoOperations(containerIpAddress, mappedPort, "mydb", "user", "pwd");
    }

    private MongoTemplate createMongoOperations(String hostname, int port, String dbName, String user, String pwd) throws DataAccessException, Exception {
        MongoCredential mongoCredentials = MongoCredential.createScramSha1Credential(user, dbName, pwd.toCharArray());
        MongoClient mongoClient = new MongoClient(new ServerAddress(hostname, port), Arrays.asList(mongoCredentials));
        Mongo mongo = new SimpleMongoDbFactory(mongoClient, dbName).getDb().getMongo();
        return new MongoTemplate(mongo, dbName);
    }
}

@BeforeClass
public static void setUp() {
    MockitoAnnotations.initMocks(this);

    startMongo();
}

我做了什么

  • 添加static到您的设置方法
  • 将ip转换为静态字段:containerIpAddress = mongo.getContainerIpAddress();
  • 添加@Configuration MongoTestConfiguration 重新定义MongoTemplate
于 2016-09-07T02:16:01.250 回答
0

@Alex 让我想到了一个更清洁的解决方案。我没有在我的测试套件中修改 MongoTemplate,而是将该代码移至 MongoConfiguration.java。

这是我最终解决问题的方法。

在我的 MongoConfiguration.class 我做了以下更改:

@Configuration
@EnableMongoRepositories
@ComponentScan({"com.is.hierarchies.service"})
public class MongoConfiguration extends AbstractMongoConfiguration {

String containerIpAddress;
Integer mappedPort;

@Override
public Mongo mongo() throws Exception {
    startMongo();
    return new Mongo(containerIpAddress,mappedPort);
}

@Override
public String getDatabaseName() {
    return "hierarchies_db";
}

/**
 * Starts a Mongo docker container, and configures the repository factory to use this instance.
 */
private void startMongo() {
    GenericContainer mongo = new GenericContainer("mongo:3")
            .withExposedPorts(27017);
    mongo.start();

    containerIpAddress = mongo.getContainerIpAddress();
    mappedPort = mongo.getMappedPort(27017);

}
}
于 2016-09-07T17:45:43.157 回答