Comment configurer MongDB intégré pour les tests d'intégration dans une application de démarrage de printemps?

j'ai une application de démarrage à ressort assez simple qui expose une petite API REST et récupère des données à partir d'une instance de MongoDB. Les requêtes à L'instance MongoDB passent par un dépôt de données de printemps. Quelques touches de code ci-dessous.

java prettyprint-override">// 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);
    }
}

Donc l'idée ici est d'avoir les tests d'intégration (vide pour l'instant) se connecter à l'embedded mongo instance et non le "live". Toutefois, il ne fonctionne pas. Je peux voir les tests la connexion à la "live" instance de Mongo, et si j'ai arrêter que le construire simplement échoue, car il est toujours tentant de se connecter au live instance de Mongo. Personne ne sait pourquoi il en est? Comment puis-je obtenir les tests pour me connecter à l'instance embarquée?

21
demandé sur Jon 2015-07-22 19:03:33

5 réponses

Cela fonctionne pour moi.

classe de Test:

    @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());
        }

    } 

simple MongoDB repository:

public interface GameRepository extends MongoRepository<Game, String>     {

    Game findByName(String name);
}

MongoDB test configuration:

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>
17
répondu cahen 2016-10-28 15:18:04

depuis la version 1.3 De La Botte de printemps, il y a un EmbeddedMongoAutoConfiguration classe qui sort de la boîte. Cela signifie que vous n'avez pas à créer un fichier de configuration du tout et si vous voulez changer les choses que vous pouvez encore.

L'auto-configuration pour MongoDB embarqué a été ajoutée. Une dépendance sur de.flapdoodle.embed: de.flapdoodle.intégrer.mongo est tout ce qui est nécessaire pour commencer. La Configuration, telle que la version de Mongo à utiliser, peut être contrôlée via application.propriété. Veuillez consulter la documentation pour obtenir de plus amples renseignements. ( Notes De Version De La Botte De Printemps)

la configuration la plus basique et la plus importante qui doit être ajoutée à l'application.les propriétés des fichiers est

spring.data.mongodb.port=0 (0 signifie qu'il sera sélectionné au hasard parmi ceux qui sont gratuits)

pour plus de détails, consultez: Printemps De Démarrage Docs MongoDb

27
répondu magiccrafter 2017-04-11 16:20:39

je vais remplir la réponse précédente

pom.xml

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.3.2.RELEASE</version>
</parent>
 ...
    <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>${embedded-mongo.version}</version>
    </dependency>

MongoConfig

@Configuration
@EnableAutoConfiguration(exclude = { EmbeddedMongoAutoConfiguration.class })
public class MongoConfig{
}
5
répondu panser 2016-02-14 12:17:27

dans la version 1.5.7 utilisez juste ceci:

@RunWith(SpringRunner.class)
@DataMongoTest
public class UserRepositoryTests {

    @Autowired
    UserRepository repository;

    @Before
    public void setUp() {

        User user = new User();

        user.setName("test");
        repository.save(user);
    }

    @Test
    public void findByName() {
        List<User> result = repository.findByName("test");
        assertThat(result).hasSize(1).extracting("name").contains("test");
    }

}

Et

        <dependency>
            <groupId>de.flapdoodle.embed</groupId>
            <artifactId>de.flapdoodle.embed.mongo</artifactId>
        </dependency>
5
répondu Nataniel Paiva 2017-09-27 13:51:15

assurez-vous que vous êtes explicite avec votre @ComponentScan. Par défaut,

si des paquets spécifiques ne sont pas définis, la numérisation se produit à partir du package de la classe avec cette annotation. (@Componentsscan Javadoc)

Donc, si votre TestProductApplication et ProductApplication les configurations sont toutes les deux dans le même paquet, il est possible que le ressort soit component-scannant votre ProductApplication configuration et en utilisant cela.

de plus, je recommande mettez vos haricots mongo Test dans un profil "test" ou "local" et en utilisant le @ActiveProfiles annotation dans votre classe de test pour activer le profil test/local.

3
répondu FGreg 2015-07-22 16:36:00