Realmente vale a pena testar uma unidade de um cliente de API?

38

Isso é algo que me preocupa há um tempo. Realmente vale a pena testar uma unidade de um cliente de API?

Digamos que você esteja criando uma classe pequena para abstrair as chamadas para uma API REST da loja de animais de estimação. A loja de animais de estimação é uma API muito simples e possui um conjunto básico de métodos:

  • listProducts()
  • getProductDetails(ProductID)
  • addProduct(...)
  • removeProduct(ProductID)

Ao testar isso, teríamos que criar um serviço simulado ou simular as respostas. Mas isso parece exagero; Entendo que queremos garantir que nossos métodos não parem de funcionar com erros de digitação / sintaxe, mas como estamos escrevendo funções que chamam métodos remotos e depois criando respostas falsas a partir desses métodos remotos, parece que um desperdício de esforço e que estamos testando algo que realmente não pode falhar. Pior, se o método remoto mudar, nossos testes de unidade serão aprovados enquanto o uso da produção falhar.

Tenho certeza de que estou perdendo alguma coisa, ou estou com o lado errado do bastão, ou não estou vendo a madeira para as árvores. Alguém pode me colocar no caminho certo?

Phillip B Oldham
fonte
1
Se essa API não fosse tão simples com métodos básicos, você se sentiria diferente? Até um galpão tem que enfrentar a neve.
Jeffo

Respostas:

31

O trabalho de um cliente remoto da API é emitir determinadas chamadas - nem mais nem menos. Portanto, seu teste deve verificar se emite essas chamadas - nem mais nem menos.

Claro, se o provedor da API alterar a semântica de suas respostas, seu sistema falhará na produção. Mas isso não é culpa da sua classe de cliente; é algo que só pode ser capturado em testes de integração. Ao confiar no código que não está sob seu controle, você renunciou à capacidade de verificar a correção por meio de testes internos - foi uma troca e esse é o preço.

Dito isso, testar uma classe que consiste apenas de delegações para outra classe pode ser de baixa prioridade, porque há comparativamente pouco risco de erros complexos. Mas isso vale para qualquer classe que consiste apenas de uma linha uniforme, não tem nada a ver com chamar o código de outro fornecedor.

Kilian Foth
fonte
Mmm, não tenho certeza se eu concordo. Você pode testar se foo()é chamado antes bar(), mas isso não significa que ligar foo()antes bar()é a coisa certa a fazer; um teste de unidade como esse passaria mesmo se o código estivesse errado. E se isso é tudo o que o cliente está fazendo, configurar as simulações que verificam se foo()são chamadas antes bar()é relativamente problemático para algo que pode ser verificado com uma rápida olhada no código do cliente.
Doval
1
Você pode testar se um add()método adiciona dois números corretamente, mas isso não significa que a adição é a coisa certa a ser feita neste momento no algoritmo - o add()teste de unidade seria bem-sucedido, mesmo que seu programa estivesse errado. Se for a coisa errada, seu levenshteinDistance()método é o culpado, não o add()método. Isto é exatamente o mesmo. O ponto de separar o código em métodos é sempre que cada método precisa se preocupar apenas em corrigir uma coisa.
Kilian Foth
3
Agora vejo onde discordamos! Se você confia em uma loja de animais externa, isso significa que seu sistema termina no limite HTTP; portanto, as chamadas REST emitidas são saídas e sujeitas a teste. Se você considerar a loja de animais de estimação parte deste módulo, sim, o padrão de chamadas emitidas é um detalhe da implementação e um teste de unidade não tem nenhum negócio prescrevendo nada sobre eles.
Kilian Foth
2
"Portanto, seu teste deve verificar se emite essas chamadas". Acho que essa é a perspectiva que eu estava deixando de ver. Obrigado!
Phillip B Oldham
1
Por exemplo, por exemplo, meu teste de unidade pode verificar se, dados determinados parâmetros, o corpo da solicitação que é sobre a execução é o correto?
Maria Ines Parnisari
9

Resposta curta:

Todos os métodos devem ser testados em unidade.

Resposta longa:

Sim. Vale a pena.

Estas são algumas coisas que os testes de unidade desses métodos de chamada de API devem testar:

  • Você está passando parâmetros bem formados ou corretos para as chamadas da API.
  • Que você está respondendo de acordo com certos tipos de dados retornados pelas APIs (simulados ou não), por exemplo, talvez quando a API retorna uma string vazia, seu método deve retornar um valor padrão (apenas um exemplo)
  • Que os métodos de chamada se comportam corretamente quando chamadas de API produzem um erro

Essas são as coisas que o método chamado faz que podem ser isoladas quando estou zombando do serviço da API e, testando-as bem, asseguro que os erros não sejam originados por um erro no código do cliente que chama a API.

Tulains Córdova
fonte
Você diz "zombado ou não" ... então, tudo bem testar com a API real? Posso chamá-lo de teste de integração, mesmo que pareça um teste de unidade? Ou há outra coisa para chamar isso? Eu adoraria teste que o meu invólucro API faz o que diz que faz, de alguma forma ...
Dan Rosenstark
1
@ DanRosenstark Acho que, no caso de o serviço da API não estar sendo ridicularizado, é um teste de integração.
Tulains Córdova
Você não saberia em 5 segundos se está recebendo os dados de volta corretamente ao fazer uma chamada real para a API? Como as zombarias da API não são chamadas reais, a única maneira de falharem é se elas mudarem a API ... nesse caso, seus testes simulados passariam, mas as chamadas reais falhariam. Parece inútil
MattE 04/07
5

Estes não seriam testes de unidade, porque você está testando a entrada e a saída do seu sistema, mais como testes de integração limitados.

Seja muito cauteloso ao dizer "parece um desperdício de esforço e que estamos testando algo que realmente não pode falhar" - pode falhar, falhará, provavelmente falhará de maneiras que você não pode antecipar, o as falhas serão piores se você não tiver testes.

O erro que você está cometendo aqui está relacionado à invenção das rodas: fazer chamadas para serviços remotos e APIs é um cenário muito comum, portanto existem algumas ferramentas muito boas para ajudá-lo a testar isso. A última vez que trabalhei em um aplicativo conectado a serviços remotos, usei o SoapUIque pode examinar um serviço e fazer chamadas simuladas para esse serviço ou se comportar como uma cópia local do servidor, na qual você pode fazer chamadas de teste e acompanhar as solicitações e respostas. Demorou alguns minutos para configurar e também era muito rápido para atualizar se a interface remota fosse alterada. Eu não o usei em um cenário REST, mas mesmo que não funcione bem para isso (ou talvez alguém esteja lendo esta resposta no futuro quando existirem ferramentas melhores), você poderá encontrar uma ferramenta que possa simular um serviço para você e quando chegar a hora de implantar seu código, você ficará satisfeito por ter feito isso.

glenatron
fonte