断言模拟中没有调用任何方法
我正在使用 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
如果我想确保永远不会调用 :expense_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
现在,为了测试正确的缓存,我必须至少调用一次 :extense_method
来加载缓存。我喜欢 David Chelimsky 的解决方案,但它没有回答我的初衷,即:测试在第一次调用 SomeClass.method
后,注入的类再也不会被调用(:expense_method 也不会)
也没有其他任何东西)。
I am writing tests with Rspec2 using the Flexmock mocking framework. I expect one of my methods to cache results and want to verify this with my mock.
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
This works reasonable well if I want to make sure that :expensive_method
is never called. However, I am expecting my class to be able to do :method
without calling anything on the passed in (mock) class. Is there a way to express this?
Background: In my case, the injected class performs expensive operations and therefore results should be cached for equal queries.
Update
Thanks for the suggestions so far, maybe I'm just assuming wrong things or maybe what I want doesn't even make sense. The way I implemented my caching is by holding a class variable in SomeClass
and add to that in the :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
Now, in order to test the correct caching, I have to call :extensive_method
at least once to load the cache. I like David Chelimsky's solution, but it isn't answering my original intent, which is: Test that after the first call to SomeClass.method
the injected class is never called again (neither :expensive_method
nor anything else).
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
指定缓存的传统方法是在调用
method
之前声明@mock.should_receive(:exppressive_method).once
,然后调用调用该方法两次的方法。我还想为此使用两个示例:一个指定它如何使用数据,一个指定它仅检索数据一次:
此外,您不需要调用
flexmock_verify
,因为自动发生。The conventional way to specify caching is to say
@mock.should_receive(:expensive_method).once
before invokingmethod
at all, and then invoke the method that calls it twice.I also like to use two examples for this: one to specify how it uses the data, one to specify that it only retrieves the data once:
Also, you don't need to call
flexmock_verify
, as that happens automatically.当然,不对模拟对象设置任何期望就可以实现这一点。对模拟进行的任何调用都会导致意外的调用失败(我承认我从未使用过 Flexmock,但我使用过的所有其他模拟框架都是这样工作的)。
不幸的是,实际上没有任何方法可以在测试中明确这一点。也许更改测试名称来指示它,也许类似于“方法使用缓存结果而不调用模拟对象”。
Surely not setting any expectations on the mocked object will achieve this. Any call made to the mock will result in an unexpected call failure (I'll admit I've never used Flexmock but every other mocking frame work I've used works this way).
Unfortunately there isn't really any way to make this explicit in the test. Maybe change the test name to indicate it, maybe something like "method uses cached result without calling mocked object".