我正在使用Flexmock模拟框架用Rspec2编写测试。我希望我的一种方法可以缓存结果,并希望用我的模拟验证这一点。
describe SomeClass do
before do
@mock = flexmock()
end
after do
@mock.flexmock_verify()
end
it "method caches results"
c = SomeClass.new(@mock)
c.method
@mock.should_receive(:expensive_method).never
c.method.should == ['A']
end
end
如果我想确保永远不会调用:expensive_method
,这样做效果很好。但是,我希望我的班级能够在不调用传入(模拟)类的情况下执行:method
。有没有办法表达这个?
后台:在我的情况下,注入的类执行昂贵的操作,因此应该为相同的查询缓存结果。
更新
感谢到目前为止的建议,也许我只是假设错误或者我想要的甚至没有意义。我实现缓存的方法是在SomeClass
中保存一个类变量,并在:method
中添加一个:
def SomeClass
@@cache_map = {}
def method
# extract key
return @@cache_map[key] if @@cache_map.has_key?(key)
# call :expensive_method to get result
@@cache_map[key] = result
return result
end
end
现在,为了测试正确的缓存,我必须至少调用:extensive_method
一次才能加载缓存。我喜欢David Chelimsky的解决方案,但它并没有回答我的原始意图,即:在第一次调用SomeClass.method
之后测试注入的类永远不再被调用(既不是:expensive_method
也不是其他任何东西)。
答案 0 :(得分:9)
指定缓存的传统方法是在调用@mock.should_receive(:expensive_method).once
之前说method
,然后调用调用它的方法两次。
我还想为此使用两个示例:一个用于指定它如何使用数据,一个用于指定它仅检索一次数据:
describe Client do
let(:service) { flexmock() }
let(:client) { Client.new(service) }
it "uses data retrieved from service" do
service.stub(:expensive_method).and_return('some data')
client.method.should eq('some data')
end
it "only retrieves the data once" do
service.should_receive(:expensive_method).once
client.method
client.method
end
end
此外,您无需致电flexmock_verify
,因为这会自动发生。
答案 1 :(得分:1)
当然,在模拟对象上设置任何期望都不会实现此目的。对模拟进行的任何调用都会导致意外的调用失败(我承认我从未使用过Flexmock,但是我使用的其他模拟框架工作都是这样的。)
不幸的是,在测试中没有任何方法可以明确这一点。也许更改测试名称来表示它,也许类似“方法使用缓存结果而不调用模拟对象”。