如何测试方法是否在 RSpec 中被调用但不覆盖返回值 [英] How to test if method is called in RSpec but do not override the return value
问题描述
已经有问题与此类似,但它们都将返回值覆盖为 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_user
在 run_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.
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屋!