Testando sua aplicação
Testando APIs do retrofit com MockWebServer
Introdução
Na maioria dos projetos que participei sempre existiu a preocupação em relação a parte de qualidade do código, refletida na automação de testes. Sempre notei que os desenvolvedores costumam testar os repositórios, mas muitas vezes acabam negligenciando a escrita de testes para a interface
da camada de serviço quando se usava retrofit.
Por que devemos automatizar testes?
Testes unitários não garantem o baixo indice de crashes em seu app ou redução dos números de bugs, todavia, ajudam em:
- Certificar que componente está funcionando para determinados cenários.
- Documentar de como utilizar as classes
- Fornecer segurança para as pessoas do time entregar alterações em código legado sem o receio de entregar algo com defeitos, pois o feedback automatizado serve como essa validação.
- Influenciar na criação de componentes desacoplados, pois a complexidade pode fornecer sinais de
code smell
. - Economizar tempo no depuramento de bugs, pois os testes podem indicar partes que estão funcionando corretamente.
Por que eu deveria testar meus serviços?
Essa pergunta é simples e a resposta ainda mais. Precisamos testar essas interfaces pois mesmo que utilizando uma interface do retrofit, precisamos garantir que nossa API foi escrita corretamente para ter a certeza que nossas requests estão sendo realizadas corretamente.
Retrofit
É um cliente HTTP para Android e Java imensamente utilizado pela comunidade Android, com suporte nativo para coroutines através de suspend functions
. Para mais informações, clique aqui e leia a documentação oficial.
MockWebServer
É uma biblioteca desenvolvida pela Square que tem como objetivo viabilizar o mock do comportamento de um servidor na internet para você utilizar em seus testes, sem a necessidade de uso de internet.
Mão na massa
Primeiro, vamos declarar nossas dependências, como descrito no gist abaixo:
o pacote dev.thiagosouto:file-butler:0.3.0
é uma lib que estou desenvolvendo que tem como objetivo ler arquivos de resources e fornecer algumas extensões para GSON/Moshi, auxiliando a minha produtividade na escrita de alguns testes.
Agora, vamos criar nossa API utilizando o retrofit:
Lendo atentamente o código podemos ver 3 partes que podem quebrar e a criação de testes podem mitigar esses riscos:
- Se estamos utilizando o relative path correto, isto é, o caminho que foi definido na anotação
@GET
- Se os parâmetros da request estão corretos
- Uma vez que estamos utilizando o
GsonConverter
, precisamos validar se o objeto retornado pelo serviço foi construído corretamente, isto é, checar a descerliazação doJSON
para a instância de objeto correta.
Criando o teste
Primeiro, precisamos criar a resource do JSON que será utilizado para resposta, por isso copiaremos o arquivo top_rated_movies.json
no diretório test/resources
.
arquivo top_rated_movies.json
Como o método a ser testado possui o operador suspend
, precisamos que essa função seja executada dentro de um CoroutineScope
, para isso, utilizamos o runBlocking
Para inicializar o MockWebServer
, basta criar uma instância com o construtor padrão e executar o método start
.
Algumas observações bem importantes:
- Segundo a documentação do
MockWebServer
, devemos utilizar uma instância para cada teste. start
deve ser executado apenas uma vez, caso contrário, será lançada umaIllegalArgumentException
informando que o servidor já foi iniciado.shutdown
deverá ser executado após cada teste, finalizando o servidor iniciado.- o método
readfile
é um método de uma biblioteca que estou desenvolvendo para auxiliar meus testes, ele se encontra publicado no Maven Central e para utilizar em seu projeto, basta declarar a dependênciadev.thiagosouto:file-butler:0.3.0
no escopo do seu teste. Seu código fonte se encontra disponível nesse repositório.
Após entendermos os pontos acima, e escrevendo o resto do teste, o arquivo ficou assim:
Olhando para o teste acima, o que fizemos foi:
- Entre as linhas 3 e 4 estamos iniciamos o
MockWebServer
, na linha 5 criamos oMockResponse()
para setar obody
com o arquivo que vamos ler do nosso JSON que mostrei anteriormente. - Entre as linhas 6 e 9, estamos iniciando o retrofit utilizando como base a url do nosso server local, iniciado pelo
MockWebServer
. O métodoserver.url(relativePath)
cria umaurl
juntando ohost
do servidor e o relative path. - Na linha 11 iniciamos a API do
MoviesApi
, através do retrofit que recebe a classe como argumento no métodoretrofit.create
. - Executamos a chamada para o endpoint com os argumentos
- Acessamos a request recebida pelo
MockWerbServer
através do métodoserver.takeRequest()
. - Finalizamos o server
- Executamos as asserções para verificar o conteúdo da request
- Executamos a asserção para ver se o objeto de resposta foi construído corretamente.
Bônus
O MockWebServer
também oferece a opção de implementar um Dispatcher
, isto é, fazer o mock de chamadas para relative paths específicos, demonstrado no exemplo abaixo:
Conclusão
Através da utilização do MockWebServer
foi possível testar com facilidade pontos importantes que as vezes acabam sendo ignorados no desenvolvimento, como por exemplo, a request que está sendo enviada para o servidor.
Esse foi o primeiro post da serie “Testando sua aplicação”, onde tem como objetivo mostrar a criação de componentes de arquitetura importantes para o desenvolvimento android junto com seus testes.