Com testar APIs externas com Webmock e VCR no RSpec
Tags: rails, api, testing, rspec
Published: 2023-10-14 12:00:19

Bora falar como podemos testar **API externas** a nossa aplicação em nossas aplicações utilizando Webmock e VCR, para este artigo estarei usando a suite de teste RSpec. Vou tentar ser bem minimalista e direto nas explicações*.*

💎 *Os exemplos serão feitos em um app Rails*

## **🌐 Webmock**

O [webmock](https://github.com/bblimke/webmock) é uma gem que nos permite criar stubs de chamadas HTTP, ou seja, ela permite criar retornos falsos para algum serviço de internet, mas sem fazer a chamada real. 


### ***Configurando***

Adicionar no Gemfile

```ruby
group :test do
  gem "webmock"
end
```

Dentro do seu arquivo spec/spec_helper adicionar o seguinte `require`

```ruby
require 'webmock/rspec'
```

Rodar bundle install para instalar a gem

```ruby
bundle install
```

Com isso as sua chamadas HTTP já ficam desabilitadas e o Webmock exigira que você realiza o stub dos retornos, mas fazer esses mocks/retornos para toda nova API que vamos testar pode ser tornar chato e cansativo, nesta parte que entra o VCR, que vai fazer isso “automagicamente” para nós, bora ver como isso pode ser feito.

## 📼 VCR

A [gem VCR](https://github.com/vcr/vcr) grava as iterações de suas chamadas para que o resultado dessas chamadas sejam utilizados no futuro, em outras palavras ela cria o stub para nós, realizando a chamada real uma única vez, após isso utiliza esse resultado para os testes.


### ***Configurando***

Adicionar no Gemfile

```ruby
group :test do
  gem "vcr"
end
```

Adicionar esse trecho de código dentro de *spec_helpers*:

```ruby
VCR.configure do |config|
  config.cassette_library_dir = "spec/fixtures/cassettes"
  config.hook_into :webmock
  config.configure_rspec_metadata!
end
```

A propriedade `cassette_library_dir` se refere ao local onde os retornos das APIs serão armazenados, já a `hook_into` nos diz que o webmock (que vimos no tópico anterior) é usado para desabilitar as chamadas http quando necessário e o `configure_rspec_metadata!` possibilita adicionar uma propriedade em nossos testes rspec para deixa-los menos verbosos ao usar o VCR, quando formos para o código isso ficará mais claro.

## 👨‍💻Testando

Para testar vou realizar uma simples chamada get para a API do **JSON Placeholder** em meu teste.

```ruby
describe 'ServiceApi' do
  it 'get a post', :vcr do
    response = Net::HTTP.get('jsonplaceholder.typicode.com', '/posts/1')
    expect(response.code).to eq '200'
end
```

Perceba que no meu `it`, eu adicionei o argumento `:vcr`, basicamente com isso eu já informo para o RSpec que o teste usará o VCR, caso vc tenha multiplos teste, é possível adicionar o argumento diretamente no `describe` de seu teste.

Ao rodar o teste, temos a seguinte situação

```ruby
1 example, 0 failures
```

Ele passou como esperado, peceba que foi gerado um arquivo no diretório que configuramos na propriedade `cassette_library_dir` do VCR com o nome do teste, isso demontra que o VCR fez a chamada e armazenou o conteúdo num arquivo yml, agora as próximas vezes que esse mesmo teste for executado, o RSpec vai consultar este arquivo (que pode ser chamado de cassete) e não realizará uma chamada real, caso você precise regerar o arquivo, basta excluílo e rodar o teste novamente.

Bacana né? Essa é uma forma bem simples de trabalharmos com APIs externas em nossos testes e garantirmos que não teremos falhas intermitentes.