Как сделать тестовый пример интеграции ActiveResource? - PullRequest
0 голосов
/ 10 октября 2018

Я разрабатываю внутренний API с использованием Rails и собираюсь использовать ActiceResource для доступа к нему.Я хочу сделать интеграционные тесты (то есть отправлять запросы http на контроллеры в тестовой среде), используя ActiveResource, но не могу понять, как настроить тестовые случаи.

В обычных интеграционных тестах вы отправляете запросыв ваше собственное приложение с методами get / post.Каким-то образом я должен сказать ActiceResource подключиться к моему приложению, а не устанавливать реальное http-соединение.

Все примеры тестирования ActiveResource, которые я вижу, используют макеты.Я хотел бы избежать этого и вместо этого запустить свои тесты для моего кода контроллера.Я использую Rails 5 и Minitest.

Ниже приведен тестовый код, который явно не работает.Если я попытаюсь запустить его, он выдаст ошибку:

require 'test_helper'

module MyApp
  class User < ActiveResource::Base
    self.site = 'http://www.example.com'
  end
end

class UserFlowsTest < ActionDispatch::IntegrationTest
  test "should get index" do
    users = MyApp::User.all

    assert_response :success
  end
end


▶ rails test test/integration/user_flows_test.rb
NoMethodError: undefined method `response_code' for nil:NilClass
    actionpack (5.2.1) lib/action_dispatch/testing/assertions/response.rb:81:in `generate_response_message'
    actionpack (5.2.1) lib/action_dispatch/testing/assertions/response.rb:31:in `assert_response'
    test/integration/user_flows_test.rb:13:in `block in <class:UserFlowsTest>'

1 Ответ

0 голосов
/ 30 октября 2018

Я нашел способ сделать это.Это хак, но, похоже, работает хорошо.

В IntegrationTest Rails определяет методы get / post / etc helpers, которые вы затем используете в тестовых примерах для подключения вашего приложения Rails.Чтобы ActiveResource использовал методы-помощники вместо реального HTTP-запроса, я включил метод AR-запроса.Я использовал глобальную переменную для отправки текущего контрольного примера и для доступа к вспомогательным методам.

# Include this in test_helper.rb into ActiveSupport::TestCase class
module ActiveResourceMonkeyPatching
  module ::ActiveResource
    # We need to monkey patch AR:Connection to use IntegrtionTest helper
    # methods (get, post, ...) instead of Net:Http
    class Connection
      private

      # Makes a request to the remote service.
      def request(method, path, *arguments)
        result = ActiveSupport::Notifications
                .instrument('request.active_resource') do |payload|
          payload[:method] = method
          payload[:request_uri] =
            "#{site.scheme}://#{site.host}:#{site.port}#{path}"
          payload[:result] =
            $test.send(method,
                      path,
                      { params: arguments.first, headers: arguments.last }) &&
            $test.response
        end
        handle_response(result)
      rescue Timeout::Error => e
        raise TimeoutError.new(e.message)
      rescue OpenSSL::SSL::SSLError => e
        raise SSLError.new(e.message)
      end
    end

    # Lets also predefine site so we don't need to configure those in test cases
    class Base
      self.site = 'http://www.example.com'
    end
  end

  # We also monkey patch IntegrationTest to set the '$test' global variance which is
  # needed in ActiveResource
  class ActionDispatch::IntegrationTest
    def setup
      $test = self
      super
    end
  end
end

С тех пор, как я начал патчить обезьяну, я также добавил еще несколько для передачи глобальной переменной и установки атрибута dummy site.Фактический тестовый пример прост, см. Ниже.Поскольку мы выполняем это как обычный IntergrationTest, все исправления в пользовательской модели загружаются как обычно.

require 'test_helper'

module MyApp
  class User < ActiveResource::Base
  end
end

class UserFlowsTest < ActionDispatch::IntegrationTest
  test "should get index" do
    users = MyApp::User.all

    assert_response :success
  end
end

Это хак :). Использование патчей для обезьян означает, что вышеуказанное решение работает с текущими версиями Rails и ActiveResource и завершится неудачей, если и когда они будут обновлены.Если кто-то найдет другой способ решить эту проблему, мне было бы интересно узнать.

...