1. Visão geral
Neste tutorial, aprenderemos como usar a solução MongoDB incorporada do Flapdoodle junto com o Spring Boot para executar testes de integração do MongoDB sem problemas.
MongoDB é um banco de dados de documentos NoSQL popular . Graças à alta escalabilidade, fragmentação integrada e excelente suporte da comunidade, muitas vezes é considerado “o Armazenamento NoSQL” por muitos desenvolvedores.
Como acontece com qualquer outra tecnologia de persistência, é fundamental poder testar facilmente a integração do banco de dados com o restante de nosso aplicativo . Felizmente, o Spring Boot nos permite escrever esse tipo de teste facilmente.
2. Dependências do Maven
Primeiro, vamos configurar o pai Maven para nosso projeto Boot.
Graças ao pai não precisamos definir a versão para cada dependência do Maven manualmente .
Naturalmente, usaremos o Spring Boot:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.6.1</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
Você pode encontrar a versão de inicialização mais recente aqui.
Como adicionamos o pai do Spring Boot, podemos adicionar as dependências necessárias sem especificar suas versões:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
spring-boot-starter-data-mongodb habilitará o suporte Spring para MongoDB:
<dependency>
<groupId>de.flapdoodle.embed</groupId>
<artifactId>de.flapdoodle.embed.mongo</artifactId>
<scope>test</scope>
</dependency>
de.flapdoodle.embed.mongo fornece MongoDB incorporado para testes de integração.
3. Teste usando o MongoDB incorporado
Esta seção abrange dois cenários:teste Spring Boot e teste manual.
3.1. Teste de inicialização do Spring
Depois de adicionar de.flapdoodle.embed.mongo dependência O Spring Boot tentará baixar e iniciar automaticamente o MongoDB incorporado ao executar testes.
O pacote será baixado apenas uma vez para cada versão para que os testes subsequentes sejam executados muito mais rapidamente.
Nesta fase, devemos ser capazes de iniciar e passar no teste de integração de amostra JUnit 5:
@DataMongoTest
@ExtendWith(SpringExtension.class)
public class MongoDbSpringIntegrationTest {
@DisplayName("given object to save"
+ " when save object using MongoDB template"
+ " then object is saved")
@Test
public void test(@Autowired MongoTemplate mongoTemplate) {
// given
DBObject objectToSave = BasicDBObjectBuilder.start()
.add("key", "value")
.get();
// when
mongoTemplate.save(objectToSave, "collection");
// then
assertThat(mongoTemplate.findAll(DBObject.class, "collection")).extracting("key")
.containsOnly("value");
}
}
Como podemos ver, o banco de dados embutido foi iniciado automaticamente pelo Spring, que também deve ser logado no console:
...Starting MongodbExampleApplicationTests on arroyo with PID 10413...
3.2. Teste de configuração manual
O Spring Boot iniciará e configurará automaticamente o banco de dados incorporado e, em seguida, injetará MongoTemplate instância para nós. No entanto, às vezes podemos precisar configurar o banco de dados Mongo incorporado manualmente (por exemplo, ao testar uma versão específica do banco de dados).
O snippet a seguir mostra como podemos configurar manualmente a instância incorporada do MongoDB. Isso é aproximadamente o equivalente ao teste Spring anterior:
class ManualEmbeddedMongoDbIntegrationTest {
private static final String CONNECTION_STRING = "mongodb://%s:%d";
private MongodExecutable mongodExecutable;
private MongoTemplate mongoTemplate;
@AfterEach
void clean() {
mongodExecutable.stop();
}
@BeforeEach
void setup() throws Exception {
String ip = "localhost";
int port = 27017;
ImmutableMongodConfig mongodConfig = MongodConfig
.builder()
.version(Version.Main.PRODUCTION)
.net(new Net(ip, port, Network.localhostIsIPv6()))
.build();
MongodStarter starter = MongodStarter.getDefaultInstance();
mongodExecutable = starter.prepare(mongodConfig);
mongodExecutable.start();
mongoTemplate = new MongoTemplate(MongoClients.create(String.format(CONNECTION_STRING, ip, port)), "test");
}
@DisplayName("given object to save"
+ " when save object using MongoDB template"
+ " then object is saved")
@Test
void test() throws Exception {
// given
DBObject objectToSave = BasicDBObjectBuilder.start()
.add("key", "value")
.get();
// when
mongoTemplate.save(objectToSave, "collection");
// then
assertThat(mongoTemplate.findAll(DBObject.class, "collection")).extracting("key")
.containsOnly("value");
}
}
Observe que podemos criar rapidamente MongoTemplate bean configurado para usar nosso banco de dados embutido configurado manualmente e registrá-lo dentro do contêiner Spring simplesmente criando, por exemplo, um @TestConfiguration com @Bean método que retornará new MongoTemplate(MongoClients.create(connectionString, “test”) .
Mais exemplos podem ser encontrados no repositório GitHub oficial do Flapdoodle.
3.3. Registro
Podemos configurar mensagens de log para o MongoDB ao executar testes de integração adicionando essas duas propriedades a src/test/resources/application.propertes Arquivo:
logging.level.org.springframework.boot.autoconfigure.mongo.embedded
logging.level.org.mongodb
Por exemplo, para desabilitar o registro, simplesmente definimos os valores como off :
logging.level.org.springframework.boot.autoconfigure.mongo.embedded=off
logging.level.org.mongodb=off
3.4. Usando um banco de dados real na produção
Como adicionamos de.flapdoodle.embed.mongo dependência usando
Para usar um banco de dados incorporado fora dos testes, podemos usar perfis Spring que registrarão o MongoClient correto (incorporado ou de produção) dependendo do perfil ativo.
Também precisaremos alterar o escopo da dependência de produção para
4. Controvérsia de teste incorporado
Usar o banco de dados incorporado pode parecer uma ótima ideia no começo. De fato, é uma boa abordagem quando queremos testar se nosso aplicativo se comporta corretamente em áreas como:
- Objeto<->Configuração de mapeamento de documentos
- Listeners de eventos de ciclo de vida de persistência personalizados (consulte AbstractMongoEventListener )
- A lógica de qualquer código trabalhando diretamente com a camada de persistência
Infelizmente, usar um servidor incorporado não pode ser considerado um "teste de integração completo" . O MongoDB embutido do Flapdoodle não é um produto oficial do MongoDB. Portanto, não podemos ter certeza de que ele se comporta exatamente como no ambiente de produção.
Se quisermos executar testes de comunicação no ambiente o mais próximo possível da produção, uma solução melhor é usar um contêiner de ambiente como o Docker.
Para saber mais sobre o Docker, leia nosso artigo anterior aqui.