在Mongo生产和测试数据库之间切换 - Java Spring Boot

时间:2016-11-13 23:45:53

标签: java spring mongodb

我有以下型号:

import org.springframework.data.annotation.Id;

@Document
public class Customer {

    @Id
    public String id;

    public String firstName;
    public String lastName;


    public Customer() {}

    public Customer(String firstName, String lastName) {
        this.firstName = firstName;
        this.lastName = lastName;
    }

    @Override
    public String toString() {
        return String.format(
                "Customer[id=%s, firstName='%s', lastName='%s']",
                id, firstName, lastName);
    }

}

以下存储库:

import java.util.List;

import org.springframework.data.mongodb.repository.MongoRepository;

public interface CustomerRepository extends MongoRepository<Customer, String> {

    public Customer findByFirstName(String firstName);
    public List<Customer> findByLastName(String lastName);

}

development数据库包含customers个集合,其中包含真实数据 - 有关真实客户的信息。 作为TDD的忠实粉丝,我创建了以下单元测试:

@RunWith(SpringRunner.class)
@SpringBootTest
@ContextConfiguration(classes = {CustomerTest.class})
public class CustomerTest {

    @Autowired
    private CustomerRepository repository;

    @Before
    public void setUp() throws Exception {
           // I want to delete the test database, not the production one
           repository.deleteAll();
    }

    @Test
    public void testCreateCustomer() {

       // save a couple of customers
       repository.save(new Customer("Alice", "Smith"));
       repository.save(new Customer("Bob", "Smith"));

       // fetch all customers
       System.out.println("Customers found with findAll():");
       System.out.println("-------------------------------");
       for (Customer customer : repository.findAll()) {
           System.out.println(customer);
       }
       System.out.println();

       // fetch an individual customer
       System.out.println("Customer found with     findByFirstName('Alice'):");
       System.out.println("--------------------------------");
       System.out.println(repository.findByFirstName("Alice"));

       System.out.println("Customers found with findByLastName('Smith'):");
       System.out.println("--------------------------------");
       for (Customer customer : repository.findByLastName("Smith")) {
           System.out.println(customer);
       }
    }       
}

我当然有SpringMongoConfig.java

@Configuration
@PropertySource(value={"classpath:application.properties"})
public class SpringMongoConfig extends AbstractMongoConfiguration {

    @Value("${spring.data.mongodb.host}")
    private String host;

    @Value("${spring.data.mongodb.port}")
    private Integer port;

    @Value("${spring.data.mongodb.database}")
    private String database;

    public @Bean
    MongoDbFactory mongoDbFactory() throws Exception {
        return new SimpleMongoDbFactory(new MongoClient(this.host + ":" + this.port), database);
    }

    public @Bean
    MongoTemplate mongoTemplate() throws Exception {
        MappingMongoConverter converter = new MappingMongoConverter(new DefaultDbRefResolver(mongoDbFactory()),
                new MongoMappingContext());
        converter.setMapKeyDotReplacement("\\+");

        MongoTemplate mongoTemplate = new MongoTemplate(mongoDbFactory(), converter);

        return mongoTemplate;

    }

    @Override
    protected String getDatabaseName() {
        return this.database;
    }

    @Override
    public Mongo mongo() throws Exception {
        return new MongoClient(this.host, this.port);
    }
}

如何在执行单元测试时在productiontest数据库之间切换?

3 个答案:

答案 0 :(得分:3)

最简单的方法是在测试中覆盖所需的属性:

@RunWith(SpringRunner.class)  
@SpringBootTest(properties = {
    "spring.data.mongodb.database=test_db"
})
@ContextConfiguration(classes = {CustomerTest.class})
public class CustomerTest {

如果您需要重新定义bean - 例如使用内存中的fongo实现,您可以创建CustomTestConfig并将其添加到您的测试中:

@RunWith(SpringRunner.class)  
@SpringBootTest(classes = TestConfig.class)
@ContextConfiguration(classes = {CustomTestConfig.class})
public class CustomerTest {

答案 1 :(得分:3)

我个人更喜欢使用嵌入式数据库进行测试。您可以使用FakeMongo

package com.backend.configuration;

import com.github.fakemongo.Fongo;
import com.mongodb.Mongo;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.mongodb.config.AbstractMongoConfiguration;
import org.springframework.data.mongodb.repository.config.EnableMongoRepositories;

@Configuration
@EnableMongoRepositories(basePackages = "com.backend.repository")
public class MongoConfiguration extends AbstractMongoConfiguration {

  private static final String DB_NAME = "test";

  @Override
  protected String getDatabaseName() {
    return DB_NAME;
  }

  @Override
  @Bean
  public Mongo mongo() {
    return new Fongo(getDatabaseName()).getMongo();
  }

  @Override
  protected String getMappingBasePackage() {
    return "com.backend.domain";
  }
}

在测试课程中:

package com.backend.repository;

import com.backend.configuration.MongoConfiguration;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = MongoConfiguration.class)
public class CustomerRepositoryTest {

}

对于开发和生产等其他配置文件,您可以使用spring boot配置文件(请参阅doc),也可以使用maven配置文件: 在application.properties中添加此属性spring.data.mongodb.host=@mongo.host@,然后在pom.xml中根据使用的个人资料进行定义:

    <profile>
        <id>dev</id>
        <activation>
            <activeByDefault>true</activeByDefault>
        </activation>
        <properties>
            <mongo.host>localhost</mongo.host>
        </properties>
    </profile>
    <profile>
        <id>prod</id>
        <properties>
            <mongo.host>mongo</mongo.host>
        </properties>
    </profile>

答案 2 :(得分:0)

如果要切换在线数据库或测试数据库,请在单元测试时使用测试数据库。您可以在数据源配置中使用@Conditional注释。 这是方法:

  1. 将课程添加到impl Conditional。其中一个在线条件,另一个是测试条件。你可以通过阅读yml config

  2. 来推动这两个条件类
  3. 将这些条件添加到您的数据源配置中:

  4. @Conditional(Online.class) @Component class OnlineDatasrouceConfig{ }

    @Conditional(OnTest.class) @Component class TestDatasrouceConfig{ }

    然后,只有当条件为真时,spring才会创建bean。

    这是条件文件: http://docs.spring.io/spring-boot/docs/1.4.1.RELEASE/reference/htmlsingle/#boot-features-condition-annotations

    并且,在运行单元测试时,还有其他一些方法可以切换测试数据库。 将@ActiveProfile("test")添加到测试类中。 spring将使用test.yml来初始化此测试类。而且,您只需要将您的测试数据库配置放在test.yml(我这样使用)