我正在编写一个调用一些外部服务的Sinatra应用程序。我显然希望我的测试能够避免调用真正的服务,所以在我拥有这个时就会这么假设
class MyApp < Sinatra::Base
get '/my_method' do
@result = ExternalServiceHandler.new.do_request
haml :my_view
end
end
在我的测试中
describe "my app" do
include Rack::Test::Methods
def app() MyApp end
it "should show OK if call to external service returned OK" do
@external_service_handler = MiniTest::Mock.new
@external_service_handler.expect :do_request, "OK"
#Do the injection
get '/my_method'
response.html.must_include "OK"
end
it "should show KO if call to external service returned KO" do
@external_service_handler = MiniTest::Mock.new
@external_service_handler.expect :do_request, "KO"
#Do the injection
get '/my_method'
response.html.must_include "KO"
end
end
我可以想到两种方法来注入它。我可以调用实例方法或通过构造函数传递依赖项。无论如何,因为机架似乎没有让我访问当前的应用程序实例,我发现这是不可能的。
我可以为此声明一个类方法,但如果可能,我更愿意使用实例。为了保持可能在每种情况下进行不同的注射,并避免在忘记回滚状态时可能损害其他测试的全局状态。
有没有办法实现这个目标?
提前致谢。
答案 0 :(得分:10)
似乎有几种选择。您可以通过构造函数传递依赖项,也可以使用设置。
构造函数Args
class MyApp < Sinatra::Base
def initialize(app = nil, service = ExternalServiceHandler.new)
super(app)
@service = service
end
get "/my_method" do
@result = @service.do_request
haml :my_view
end
end
在规范中:
describe "my app" do
include Rack::Test::Methods
let(:app) { MyApp.new(service) }
let(:service) { double(ExternalServiceHandler) }
context "when the external service returns OK" do
it "shows OK" do
expect(service).to receive(:do_request).and_return("OK")
get '/my_method'
response.html.must_include "OK"
end
end
context "when the external service returns KO" do
it "shows KO" do
expect(service).to receive(:do_request).and_return("KO")
get '/my_method'
response.html.must_include "KO"
end
end
end
设置强>
class MyApp < Sinatra::Base
configure do
set :service, ::ExternalServiceHandler.new
end
get "/my_method" do
@result = settings.service.do_request
haml :my_view
end
end
在规范中:
describe "my app" do
include Rack::Test::Methods
let(:app) { MyApp.new }
let(:service) { double(ExternalServiceHandler) }
before do
MyApp.set :service, service
end
context "when the external service returns OK" do
it "shows OK" do
expect(service).to receive(:do_request).and_return("OK")
get '/my_method'
response.html.must_include "OK"
end
end
context "when the external service returns KO" do
it "shows KO" do
expect(service).to receive(:do_request).and_return("KO")
get '/my_method'
response.html.must_include "KO"
end
end
end
答案 1 :(得分:1)
我终于设法用
做到了这一点describe "my app" do
def app
@INSTANCE
end
before do
@INSTANCE ||= MyApp.new!
end
#tests here
end
虽然我不是特别喜欢使用新的!在它正在工作的那一刻超载。我可以使用app.whatever_method
每次测试时使用的实例