[RUBY] [RSpec] Utilisez WebMock pour tester la logique à l'aide d'une API externe

Dans l'article [Ruby] Procédure de création d'une classe de liaison d'API externe à l'aide de faraday, nous avons présenté comment créer un lien avec une API externe à l'aide de faraday.

Dans le code de test logique qui utilise une API externe, il est courant de stuber les requêtes HTTP au lieu d'utiliser l'API réelle. Dans Rails, vous pouvez stuber les requêtes HTTP en utilisant un gem appelé webmock.

Cette fois, je vais vous présenter comment créer un code de test logique lié à une API externe à l'aide de WebMock.

La classe cible du code de test

Cette fois, nous allons créer un code de test pour une classe appelée QiitaClientAPI qui fonctionne avec l'API Qiita. La classe implémente une méthode appelée get_items pour obtenir une liste d'articles de Qiita.

Le code source spécifique est le suivant.

lib/qiita_api_client.rb


class QiitaApiClient
  class HTTPError < StandardError
    def initialize(message)
      super "connection failed: #{message}"
    end
  end

  class << self
    def connection
      Faraday::Connection.new('https://qiita.com') do |builder|
        builder.authorization :Bearer, "#{Rails.application.credentials.qiita[:token]}"
        builder.request  :url_encoded #Paramètres de demande de codage d'URL
        builder.response :logger #Sortie de la réponse en standard
        builder.adapter Faraday.default_adapter #Sélection de l'adaptateur. La valeur par défaut est Net::HTTP
        builder.response :json, :content_type => "application/json" #JSON analyse le corps de la réponse
      end
    end

    def get_items
      begin
        response = connection.get(
          '/api/v2/items'
        )
        response.body
      rescue Faraday::ConnectionFailed => e
        raise QiitaApiClient::HTTPError.new(e.message)
      end
    end
  end
end

Préparation

Préparez-vous à exécuter le code de test.

Configuration RSpec

Cette fois, nous utiliserons RSpec comme cadre de test. Ajoutez rspec-rails à votre Gemfile.

Gemfile


group :development, :test do
  gem 'rspec-rails'
end

Installez gem et configurez RSpec.

$ bundle install
$ rails generate rspec:install

installation de webmock

Ajoutez webmock à votre Gemfile et installez-le.

Gemfile


gem 'webmock'
$ bundle install

Implémentation du code de test

Ci-dessous, nous allons vous présenter comment écrire du code de test à l'aide de WebMock.

Test système normal

Le code de test pour le système normal est le suivant.

spec/lib/qiita_api_client_spec.rb


require 'rails_helper'

describe 'QiitaApiClient' do
  before do
    WebMock.enable! #Activer WebMock
    allow(Rails.application.credentials).to receive(:qiita).and_return({token: '123'})
  end
  describe '.get_items' do
    let(:response_body) { [{ "title": "test" }].to_json }
    before do
      WebMock.stub_request(:get, "https://qiita.com/api/v2/items").
        with(
          headers: {'Authorization' => "Bearer 123"}
        ).
        to_return(
          body: response_body,
          status: 200,
          headers: { 'Content-Type' => 'application/json' }
        )
    end
    it 'Les données peuvent être obtenues' do
      expect(QiitaApiClient.get_items).to eq(JSON.parse(response_body))
    end
  end
end

J'ai activé WebMock avec WebMock.enable! Et créé un stub de requête HTTP à WebMock.stub_request.

En utilisant WebMock, vous pouvez décrire le comportement de «quel type de requête est retourné et quel type de réponse est retourné». Cela vous permet de créer une situation simulée dans laquelle des données sont échangées via une API externe.

Pour allow (Rails.application.credentials) décrit dans before, définissez une valeur factice pour Rails.application.credentials.qiita [: token] décrit dans le code de l'application. Est pour.

Test du système anormal (occurrence d'exception)

Si le code d'application ne peut pas communiquer normalement avec l'API externe, il lève l'exception QiitaApiClient :: HTTPError avec un message d'erreur.

Le code de test du système anormal qui confirme qu'une exception s'est produite est le suivant.

spec/lib/qiita_api_client_spec.rb


require 'rails_helper'

describe 'QiitaApiClient' do

  before do
    WebMock.enable!
    allow(Rails.application.credentials).to receive(:qiita).and_return({token: '123'})
  end

  describe '.get_items' do
    let(:response_body) { { "message": "error_message", "type": "error_type" }.to_json }
    before do
      WebMock.stub_request(:get, "https://qiita.com/api/v2/items").
        to_raise(Faraday::ConnectionFailed.new("some error"))
    end
    it 'Qu'une exception se produit' do
      #Le test d'exception est attendu()Pas attendre{}Donc sois prudent
      expect{QiitaApiClient.get_items}.to raise_error(QiitaApiClient::HTTPError, "connection failed: some error")
    end
  end
end

J'ai créé un stub qui lève une exception avec to_raise dans WebMock et confirmé que l'exception est levée avec rise_error dans expect.

Code de test final

Le code de test final qui résume le système normal et le système anormal introduit cette fois est le suivant.

spec/lib/qiita_api_client_spec.rb


require 'rails_helper'

describe 'QiitaApiClient' do
  let(:qiita_base_uri) { 'https://qiita.com/api/v2' }
  before do
    WebMock.enable!
    allow(Rails.application.credentials).to receive(:qiita).and_return({token: '123'})
  end

  describe '.get_items' do
    subject { QiitaApiClient.get_items }
    context 'Succès' do
      let(:response_body) { [{ "title": "test" }].to_json }
      before do
        WebMock.stub_request(:get, "#{qiita_base_uri}/items").
          with(
            headers: {'Authorization' => "Bearer 123"}
          ).
          to_return(
            body: response_body,
            status: 200,
            headers: { 'Content-Type' => 'application/json' }
          )
      end
      it 'Les données peuvent être obtenues' do
        expect(subject).to eq(JSON.parse(response_body))
      end
    end
    context 'Échec' do
      before do
        WebMock.stub_request(:get, "#{qiita_base_uri}/items").
          to_raise(Faraday::ConnectionFailed.new("some error"))
      end
      it 'Qu'une exception se produit' do
        expect{subject}.to raise_error(QiitaApiClient::HTTPError, "connection failed: some error")
      end
    end
  end
end

Sommaire

Nous présenterons comment utiliser WebMock pour créer du code de test pour la logique liée à une API externe.

Le flux du code de test à l'aide de WebMock est le suivant.

  1. Activez WebMock avec Webmock.enable!
  2. Créez un stub de requête HTTP avec WebMock.stub_request
  3. Exécutez la méthode qui utilise l'API externe et vérifiez le résultat de l'exécution.

Je fais Twitter (@ nishina555). J'espère que vous me suivrez!

Recommended Posts

[RSpec] Utilisez WebMock pour tester la logique à l'aide d'une API externe
Utiliser Webmock avec Rspec
Comment utiliser l'API Chain
Afficher les prévisions météorologiques à l'aide d'OpenWeatherMap, une API externe de Ruby
[Rails] Code de test à l'aide de Rspec
Tester le comportement de l'enregistreur de sortie de journal lors de l'utilisation d'API de journalisation externes telles que SLF4J
Téléchargement d'images à l'aide de CarrierWave ~ Test Rspec ~
Comment insérer une bibliothèque externe
[RSpec] Test unitaire (avec gem: factory_bot)
[Pour les débutants Rails] Résumé de l'utilisation de RSpec (obtenir un aperçu)
Bibliothèque de tests unitaires Java Artery-Easy to use
[Docker] Création d'un environnement pour utiliser Hugo
Comment lire un fichier MIDI à l'aide de l'API Java Sound (spécifiez le périphérique MIDI à utiliser)