我正在使用Rails开发内部API,并且正在考虑使用ActiceResource访问它。我想使用ActiveResource进行集成测试用例(即,向测试环境中的控制器发出http请求),但无法弄清楚如何设置测试用例。
在正常的集成测试案例中,您使用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>'
答案 0 :(得分:0)
我找到了一种方法。这是一个hack,但看起来效果很好。
在IntegrationTest中,Rails定义了get / post / etc帮助程序方法,然后在测试用例中使用它们来连接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
自从我开始修补猴子以来,我还添加了一些其他方法来传递全局变量并设置伪site
属性。实际的测试用例很简单,请参见下文。由于我们将其作为常规的IntergrationTest运行,因此User模型中的所有固定装置都照常加载。
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,并且如果更新它们时将失败。如果有人找到其他解决方法,我很想知道。