Como fazer stub de APIs nos seus testes ruby

Se você escreve testes para sua aplicação provavelmente já se deparou com a situação onde você se precisa comunicar com uma API de terceiro durante os testes.

É considerado uma boa prática não conversar com serviços externos em testes e APIs não são uma exceção.

Para citar os principais problemas de conversar com uma API durante os testes:

  1. Testes lentos aguardando retorno de rede
  2. Testes intermitentes por falha de rede
  3. Limite de requisição por tempo (Google Maps, Google Charts, etc)
  4. Falta de um ambiente de testes do serviço

Todos eles podem ser evitados realizando um stub da requisição com o WebMock ou VCR.

Sempre utilizei o WebMock nos projetos que precisaram desse recurso por ser extremamente simples, mas o VCR não deixa de ser uma boa opção.

O detalhe do WebMock é que é necessário utilizar o cURL para criar a fixture com a resposta real da API.

Você pode até definir o retorno manualmente mas é mais trabalhoso fazer isso.

O que eu sempre faço é criar um diretório chamado spec/webmock com as fixtures das requisições, exemplo:

curl -is https://api.github.com > spec/webmock/api.github.com  

E em seguida configurar o WebMock para reconhecer a requisição com a fixture que acabei de criar (utilizo RSpec mas ele se integra com qualquer framework):

require 'webmock/rspec'

RSpec.configure do |config|  
  config.before do
    WebMock.disable_net_connect!(allow_localhost: true)

    stub_request(:get, "https://api.github.com").to_return(
      File.new("spec/webmock/api.github.com")
    )
  end
end  

O allow_localhost: true é necessário se você utilizar o Poltergeist porque ele conversa com o PhantomJS via websocket no localhost.

Com essa configuração, quando você realizar uma requisição em uma URL que não possui uma fixture, você receberá um WebMock::NetConnectNotAllowedError.

E quando usar uma URL que possui fixture configurada, receberá o retorno configurado no arquivo.

Existem dezenas de configurações possíveis no WebMock, confira a documentação para entender todas elas e usar a melhor opção para o seu projeto.

Referências:

  1. Managing Externals in Ruby Tests
  2. How to Stub External Services in Tests
  3. A Pattern for Stubbing Out APIs With Rspec