你好,我在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
我如何才能有效地存根外部服务,因为它在测试期间没有调用它?
有一种方法类似于:
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)
我不认为visiting a url and measuring the speed
属于Page
模型内部,设置速度是,但不是实际计算。所以我会在lib
中创建一个类,允许我测量url的速度,然后使用该类。我会允许该类注入一个存根。
所以类似这样的东西,在libpage_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.new
以返回特定的PageVisitor
,然后在该实例上存根measure_speed
,而不是更改代码(我认为代码还可以,不需要注入PageVisitor
imho)。
在您的spec/lib/page_visitor_spec.rb
中写入
describe PageVisitor
class FakeBrowser
def goto(url)
sleep 1
end
end
let(:page_visitor) { PageVisitor.new(FakeBrowser.new) }
it "measure the speed" do
page_visitor.measure_speed.should_not be_nil
end
end
这应该会让你开始。