如何测试方法是否在 RSpec 中被调用但不覆盖返回值 [英] How to test if method is called in RSpec but do not override the return value

查看:27
本文介绍了如何测试方法是否在 RSpec 中被调用但不覆盖返回值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

已经有问题与此类似,但它们都将返回值覆盖为 nil 除非 .and_return 也被调用

There are already questions similar to this, but they all override the return values to nil unless .and_return is called as well

问题

我想知道是否有一种方法可以检查是否使用 expect_any_instance_of(Object).to receive(:somemethod) 调用了一个方法,并且它可以正常运行而不会覆盖或影响.somemethod.

I am wondering if there is a way to just check if a method is called using expect_any_instance_of(Object).to receive(:somemethod) and it runs normally without overriding or affecting the return value of .somemethod.

  • rspec-3.4.0
  • 导轨 4.2

考虑以下事项:

# rspec
it 'gets associated user' do
  expect_any_instance_of(Post).to receive(:get_associated_user)
  Manager.run_processes
end

# manager.rb
class Manager
  def self.run_processes
    associated_user = Category.first.posts.first.get_associated_user
    associated_user.destroy!
  end
end

上述规范虽然有效,因为 :get_related_userrun_processes 中被调用,但是它引发了 NoMethodError: undefined method 'destroy!'对于 NilClass 正是因为我为 Post 的任何实例模拟了 :get_associated_user.

The spec above although will work because :get_associated_user is called in the run_processes, however it raises NoMethodError: undefined method 'destroy!' for NilClass precisely because I mocked the :get_associated_user for any instance of Post.

我可以添加一个 .and_return 方法,比如 expect_any_instance_of(Post).to receive(:get_associated_user).and_return(User.first) 以便它可以在不引发的情况下工作那个错误,但这已经是一个模拟的返回值(这可能会影响它下面的其余代码),而不是它在调用方法时应该返回的正确预期值.

I could add a .and_return method like expect_any_instance_of(Post).to receive(:get_associated_user).and_return(User.first) so that it will work without raising that error, but that already is a mocked return value (which might affect the rest of the code below it), and not the correct expected value it should have returned at the time the method is called.

然而,我可以指定 .and_return(correct_user) 其中 correct_user 是返回值与正常运行相同的用户.但是,这需要我模拟 Category.first.posts.first.get_related_user 序列中的每个返回值,以便它正常工作.实际问题比上述复杂得多,因此在我的情况下,存根并不是真正可行的解决方案.

I can however specify .and_return(correct_user) where correct_user is the user that is going to be the same return value as if it has ran normally. However, this will need me to mock every return value in the sequence Category.first.posts.first.get_associated_user just so that it will work normally. The actual problem is a lot more complex than above, therefore stubbing is not really a possible solution in my case.

推荐答案

您可以在流畅的界面上使用and_call_original来通过通过"接收到的消息到原始方法.

You can use and_call_original on the fluent interface to "pass through" the received message to the original method.

https://www.relishapp.com/rspec/rspec-mocks/v/2-14/docs/message-expectations/calling-the-original-method

expect_any_instance_of(Post).to receive(:get_associated_user).and_call_original

然而,使用 expect_any_instance_of 可能会告诉你你有代码味道,你应该测试行为 - 而不是实现.

However the use of expect_any_instance_of might be telling you that you have a code smell and you should be testing the behavior - not the implementation.

# test what it does - not how it does it.
it 'destroys the associated user' do
  expect { Manager.run_processes }.to change(Category.first.posts.first.users, :count).by(-1)
end

这篇关于如何测试方法是否在 RSpec 中被调用但不覆盖返回值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆