您好我在rails模型中有类似下面的代码:
class Page < ActiveRecord::Base
def calculate_page_speed(url)
browser = Watir::Browser.new :phantomjs
start = Time.now
browser.goto url
finish = Time.now
self.speed = finish - start
end
end
以下是测试:
describe Page do
context "calculate_page_speed for Page" do
let(:google) { FactoryGirl.create(:page, url: "http://www.google.com") }
it "should set the page speed" do
google.speed.should be_nil
google.calculate_page_speed
google.speed.should_not be_nil
end
end
end
如何有效地存储外部服务,以便在测试期间不调用它?
答案 0 :(得分:2)
有一种方法:
class Page < ActiveRecord::Base
def calculate_page_speed(url)
start = Time.now
browser.goto url
finish = Time.now
self.speed = finish - start
end
def browser
@browser ||= Rails.env.test? ? FakeBrowser.new : Watir.new(:phantomjs)
end
class FakeBrowser
def goto
end
end
end
但是你在prod代码中有测试代码并不是很好。
派生的解决方案是在配置中注入预期的浏览器类。
最后你可以发短信:
Watir::Browser.any_instance.stub(:goto)
答案 1 :(得分:1)
我不认为visiting a url and measuring the speed
属于Page
模型,设置速度是,而不是实际计算。所以我愿意
在lib
中创建一个允许我测量网址速度的类,然后使用该类。我会允许该类注入一个存根。
类似这样的事情,在lib\page_visitor.rb
:
class PageVisitor
def initialize(browser = Watir::Browser.new(:phantomjs))
@browser = browser
end
def measure_speed(url)
start = Time.now
@browser.goto url
finish = Time.now
finish - start
end
end
您的Page
变为:
def calculate_page_speed(url)
self.speed = PageVisitor.new.measure_speed(url)
end
通过该设置,您可以简化测试:在Page
中,您必须检查正确的函数,同样,在PageVisitor
中检查goto
是否被调用,实际上去了页面。
所以,在spec/models/page_spec.rb
中写道:
let(:google) { FactoryGirl.create(:page, url: "http://www.google.com") }
it("initial speed is zero") { google.speed.should be_nil }
describe `calculating the speed` do
before do
PageVisitor.any_instance.should_receive(:measure_speed).and_return(25)
google.calculate_page_speed
end
it "sets the speed correctly"
google.speed.should == 25
end
end
使用any_instance
可能会被视为气味,但在这种情况下,我认为这是测试它的最简单方法。如果你真的想避免它,而不是改变代码(我认为代码没问题,不需要注入PageVisitor
imho),你可以存根PageVisitor.new
来返回特定的{{1}然后你可以在那个实例上存根PageVisitor
。
在measure_speed
写
spec/lib/page_visitor_spec.rb
这应该让你开始。