Testando sua aplicação

Testando APIs do retrofit com MockWebServer

Thiago Souto
Android Dev BR
Published in
4 min readFeb 19, 2021

--

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:

  1. Certificar que componente está funcionando para determinados cenários.
  2. Documentar de como utilizar as classes
  3. 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.
  4. Influenciar na criação de componentes desacoplados, pois a complexidade pode fornecer sinais de code smell.
  5. 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:

gist com as dependências utilizadas para o teste

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:

interface com a API para acessar os endpoints do serviço e pegar filmes favoritos

Lendo atentamente o código podemos ver 3 partes que podem quebrar e a criação de testes podem mitigar esses riscos:

  1. Se estamos utilizando o relative path correto, isto é, o caminho que foi definido na anotação @GET
  2. Se os parâmetros da request estão corretos
  3. 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 do JSONpara 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.

gist com o conteúdo de inicialização do MockWebServer, com a inicialização de uma resposta

Algumas observações bem importantes:

  1. Segundo a documentação do MockWebServer, devemos utilizar uma instância para cada teste.
  2. start deve ser executado apenas uma vez, caso contrário, será lançada uma IllegalArgumentException informando que o servidor já foi iniciado.
  3. shutdown deverá ser executado após cada teste, finalizando o servidor iniciado.
  4. 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ência dev.thiagosouto:file-butler:0.3.0no 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:

test completo do endpoint utilizando MockWebvServer

Olhando para o teste acima, o que fizemos foi:

  1. Entre as linhas 3 e 4 estamos iniciamos o MockWebServer, na linha 5 criamos o MockResponse() para setar o body com o arquivo que vamos ler do nosso JSON que mostrei anteriormente.
  2. Entre as linhas 6 e 9, estamos iniciando o retrofit utilizando como base a url do nosso server local, iniciado pelo MockWebServer. O método server.url(relativePath) cria uma url juntando o host do servidor e o relative path.
  3. Na linha 11 iniciamos a API do MoviesApi, através do retrofit que recebe a classe como argumento no método retrofit.create.
  4. Executamos a chamada para o endpoint com os argumentos
  5. Acessamos a request recebida pelo MockWerbServer através do método server.takeRequest().
  6. Finalizamos o server
  7. Executamos as asserções para verificar o conteúdo da request
  8. 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:

gist demonstrando o uso da feature dispatcher disponível para o MockWebServer

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.

Links

  1. https://github.com/square/okhttp/tree/master/mockwebserver
  2. https://square.github.io/retrofit/

--

--