Ruby RSpe c Net: HTTP - как проверить полезную нагрузку запроса, как ожидалось, при имитации ответа - PullRequest
0 голосов
/ 10 июля 2020

Я очень !! new ruby и Rspe c пользователь изо всех сил пытается понять, как выполнить модульное тестирование того, что запрос API установил ожидаемую полезную нагрузку запроса, при этом имитируя ответ от внешнего API. Я реализовал запросы API, используя Net: HTTP, чтобы ограничить зависимости.

Метод тестируемый

 def lint (url, path, headers={ "Content-Type" => "application/json" }, timeout=10)
            if yamlContent = GitLab::Lint::Client::YamlFile.new(path).get_json_content()
            
              uri = URI.parse(url)

              req = Net::HTTP::Post.new(uri, headers)
              req.body = { content: yamlContent }.to_json
              
              https = Net::HTTP.new(uri.host, uri.port)
              https.use_ssl = true
              https.verify_mode = OpenSSL::SSL::VERIFY_PEER
              
              response = https.request(req)
          
              case response
                  when Net::HTTPSuccess
                      puts "Linting request successful"
                      return JSON.parse(response.body)
                  when Net::HTTPUnauthorized
                      abort("#{response.message}: invalid token in api request?")
                  when Net::HTTPServerError
                      abort('error' => "#{response.message}: server error, try again later?")
                  when Net::HTTPBadRequest
                      puts "Bad request..." + req.body
                      abort("#{response.message}: bad api request?")
                  when Net::HTTPNotFound
                      abort("#{response.message}: api request not found?")
                  else
                      puts "Failed validation\nJSON payload :: #{req.body}\nHTTP Response: #{response.message}"
                      abort("#{response.message}: failed api request?")
              end
            else
              abort("\nLint request failed, problem encountered reading yaml file")
            end
end

RSpe c test

require "gitlab/lint/client/api"

RSpec.describe Gitlab::Lint::Client::Api do
    
    describe "#initialize" do
        it "initialises" do          
            api = Gitlab::Lint::Client::Api.new
            expect(api).to be_instance_of(Gitlab::Lint::Client::Api)
        end
    end

    describe "#lint" do
        before(:each) do
            @response = instance_double(Net::HTTPSuccess, body: @response_body, message: 'OK')
            @response_body = { 'status' => 'valid', 'errors' => [] }.to_json
            
            @request_mock = instance_double(Net::HTTP::Post)
            allow(@request_mock).to receive(:[]=)
            allow(@request_mock).to receive(:body=)
            allow(Net::HTTP::Post).to receive(:new).and_return(@request_mock)

            @http_client_mock = instance_double(Net::HTTP)
            allow(@http_client_mock).to receive(:use_ssl=)
            allow(@http_client_mock).to receive(:verify_mode=)
            allow(@http_client_mock).to receive(:request)
            allow(Net::HTTP).to receive(:new).and_return(@http_client_mock)
            allow(@http_client_mock).to receive(:request).with(@request_mock).and_return(@response)
                  
            @endpoint_url = 'http://gitlab.com'

            @fileName='test.yml'
            
            allow(File).to receive(:exist?).with(@fileName).and_return(true)
            allow(File).to receive(:readable?).with(@fileName).and_return(true)
            allow(YAML).to receive(:load_file).with(@fileName).and_return("image: ruby:latest")
        end

        it "lints successfully" do
           
            # for a valid case we want:
            # - test that the request body was set with content as expected
            # - simulate the response to be { status: "valid", "errors": []}

            api = Gitlab::Lint::Client::Api.new
            api.lint(@endpoint_url, @fileName)

            expect(@request_mock.body).to have_received({ content: {'image' => 'ruby:latest'} }.to_json)
        end
    end
end

Запуск теста дает следующий ошибочный вывод:

Gitlab::Lint::Client::Api
  #initialize
    initialises
  #lint
OK: failed api request? # this output signifies that the case structure has not recognised the response as a HTTPSuccess instance

Ответ не рассматривается как экземпляр Net :: HTTPSuccess в структура корпуса моего тестируемого метода lint . Как смоделировать экземпляр Net :: HTTPSuccess ?

1 Ответ

1 голос
/ 11 июля 2020

Популярный способ сделать это называется VCR . Вы можете найти множество документации и RailsCast на сайте проекта. В основном это работает так:

  • Вы устанавливаете видеомагнитофон в «режим записи».
  • Вы делаете запрос к реальному бэкэнду. Видеомагнитофон записывает запрос и ответ.
  • Вы устанавливаете видеомагнитофон в режим «воспроизведения».
  • Когда вы запускаете свои тесты, вы можете использовать видеомагнитофон, чтобы делать утверждения о запросе и ответе (другими словами , что он соответствует вашим ожиданиям).

Это надежный способ проверить, что HTTP-запросы выполняют именно то, что вы от них хотите.

...