Escrevendo testes unitários para seus repositórios MongoDB usando o FlapDoodle Embedded Mongo
Tags: kotlin, tdd, mongodb
Published: 2020-08-01 18:46:54

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/nio2c23dwy786bdjk99m.jpg)

Um aspecto do desenvolvimento de software que vem me interessando cada vez mais é qualidade. Posso afirmar com certeza que após começar a praticar ativamente TDD (Test driven development) a qualidade do meu código e das minhas entregas aumentou de forma exponencial. Mais que isso, praticar TDD plantou a semente da preocupação contínua com qualidade.

Pretendo abordar em uma séria de artigos algumas das práticas que me ajudam a conseguir aplicar o TDD de forma efetiva e que moldaram minha abordagem sobre qualidade no desenvolvimento de software.

Para começar, escolhi um assunto que tem um certo potencial de polêmica: Testes unitários de repositórios usando uma instancia embedded do banco.

Polêmico por 2 motivos:

* Pode ser questionável a necessidade de testar a camada repositório (e, em nível mais essencial, até mesmo a necessidade de efetivamente escrever o código nessa camada)
* Partindo do pressuposto que você vê valor no item anterior, uma abordagem alternativa - e muito difundida - é subir uma instância do banco no docker, criar um database com sufixo "-test" e executar seus testes nesse Database.

Pessoalmente, sou super fã de docker e de "conteinerização", mas vejo duas vantagens matadoras em usar a abordagem "embedded":

1. Independência dos container - não sabemos com certeza as características do ambiente que os desenvolvedores contarão. Questões como diferentes privilégios de acesso e até mesmo impossibilidade total de levantar containers devem ser levadas em conta
2. É  mais rápido e mais fácil levantar uma instância embedded do que dropar database a cada execução de testes. 

Um ponto de resistência de muitos desenvolvedores em aplicar o TDD é a divisão de foco entre o teste e o código de produção. Quanto mais tempo entre as interações, mais essa sensação de perda de foco é maximizada. Acredito que a decisão de qual estratégia adotar para os testes deve ter como preocupação fundamental fornecer a melhor experiência possível para o desenvolvedor.

Para o restante desse artigo, mostrarei uma abordagem para testar repositórios MongoDB utilizando o projeto Flapdoodle. 
Usarei Kotlin como linguagem nos exemplos e no projeto que disponibilizo de modelo https://github.com/the-sidh/zmovies
O MongoDB é o banco que eu mais tenho usado, tanto em projetos pessoais quanto profissionalmente. Ele é amplamente usado no mercado, e por isso acredito ser relevante para essa abordagem.

## Flapdoodle Embedded MongoDB
O ([Flapdoodle](https://github.com/flapdoodle-oss/de.flapdoodle.embed.mongo)) é um projeto open source que tem como objetivo prover uma plataforma para neutra para rodar testes unitários no MongoDB.
Basicamente, precisamos subir um um processo do MongoDB.

```
fun start(val host: String, val port: Int) {
    val starter = MongodStarter.getDefaultInstance()
    val mongodConfig = MongodConfigBuilder()
        .version(Version.Main.V4_0)
        .net(Net(host, port, Network.localhostIsIPv6()))
        .build()
    val mongodExecutable: MongodExecutable = starter.prepare(mongodConfig)
    val mongodProcess: MongodProcess = mongodExecutable.start()
}
```

Feito isso, temos nosso processo do MongoDB rodando.
No projeto de exemplo, isolei esses objetos em uma classe holder, para poder fazer referencia a ela por dentro de uma classe extension do JUnit5

```
override fun beforeAll(context: ExtensionContext?) {
        flapDoodleHolder.start()
    }

    override fun afterAll(context: ExtensionContext?) {
        flapDoodleHolder.stop()
    }

    override fun beforeEach(context: ExtensionContext?) {
        flapDoodleHolder.clean()
    }
}
```

O código de referência pode ser encontrado aqui:

[FlapDoodleHolder.kt](
https://github.com/the-sidh/zmovies/blob/master/src/test/kotlin/com/thesidh/zmovie/storage/holder/FlapDoodleHolder.kt)

E aqui:

[MongoDBExtension.kt](https://github.com/the-sidh/zmovies/blob/master/src/test/kotlin/com/thesidh/zmovie/storage/extension/MongoDBExtension.kt)

Uma vez feito isso, consigo utilizar toda essa instância embedded para executar meus testes. Na classe de teste, basta fazer referência à extension:

```
@ExtendWith(MongoDBExtension::class)
class MongoDBMoviesRepositoryTest(private val mongoDatabase: MongoDatabase) {
(...)
}
```

E a partir daí, é só felicidade! 

Happy TDD!