断言模拟中没有调用任何方法

发布于 2024-10-06 12:34:14 字数 1160 浏览 0 评论 0原文

我正在使用 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

原谅过去的我 2024-10-13 12:34:14

指定缓存的传统方法是在调用 method 之前声明 @mock.should_receive(:exppressive_method).once,然后调用调用该方法两次的方法。

我还想为此使用两个示例:一个指定它如何使用数据,一个指定它仅检索数据一次:

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,因为自动发生。

The conventional way to specify caching is to say @mock.should_receive(:expensive_method).once before invoking method 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:

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

Also, you don't need to call flexmock_verify, as that happens automatically.

樱桃奶球 2024-10-13 12:34:14

当然,不对模拟对象设置任何期望就可以实现这一点。对模拟进行的任何调用都会导致意外的调用失败(我承认我从未使用过 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".

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文