ruby - 从间谍调用原始方法
问题描述
我有一个服务对象,看起来像这样:
class Service
def call
do_something if anything
end
private
def do_something
# do something
end
end
我想测试do_something
在某些情况下调用的那个。
我试着写这样的东西:
RSpec.describe Service do
it 'calls do_something' do
service = instance_double(Service)
service.stub(:do_something)
expect(Service).to receive(:new).and_return service
Service.new.call
expect(service).to have_received(:do_something)
end
end
显然这不起作用,因为我没有call
为service
. 但是,如果我使用service = instance_double('Service', call: true)
它不会调用call
,所以do_something
永远不会被调用。
allow(service).to receive(:call).and_call_original
如果可能的话,我正在寻找类似的东西(也许在这种情况下instance_double
用object_double
which 替换更有意义。有这样的东西吗?
解决方案
正如您已经尝试并看到的那样,它and_call_original
仅适用于部分双打,因此无法按照文档所述尝试将其与其他类型的双打一起使用。
如果我们仔细查看部分双文档,我们可以看到它partial double
被描述为:
A partial test double is an extension of a real object in a system that is instrumented with
test-double like behavior in the context of a test. This technique is very common in Ruby
because we often see class objects acting as global namespaces for methods. For example,
in Rails:
person = double("person")
allow(Person).to receive(:find) { person }
In this case we're instrumenting Person to return the person object we've defined whenever
it receives the find message. We can also set a message expectation so that the example
fails if find is not called:
person = double("person")
expect(Person).to receive(:find) { person }
RSpec replaces the method we're stubbing or mocking with its own test-double like method.
At the end of the example, RSpec verifies any message expectations, and then restores the
original methods.
Note: we recommend enabling the verify_partial_doubles config option.
上面他们说:A partial test double is an extension of a real object
这意味着做expect(Service.new).to receive(:call).and_call_original
将是有效的,因为我们是在一个最初是创建的真实世界对象的部分双精度上进行的,并且期望对其进行设置,使其成为部分双精度。但是如果我们这样做expect(object_double(Service.new)).to receive(:call).and_call_original
将不起作用,因为我们将这个期望设置在一个纯双精度上,它是一个验证双精度,而不是现实世界对象的扩展。这意味着在部分双精度中,我们直接针对真实世界或真实系统对象,但在纯双精度情况下,我们正在与双精度对话。这是基于文档类比,它适用于其他类型的双打,而不仅仅是object_double
.
如果您在该方法的文档中查看此链接and_call_original
,您会注意到这句话:
Use and_call_original to make a partial double response as it normally would
这是有道理的,因为它会像往常一样做出响应,并且通常在系统中,我们在真实对象或类上调用原始方法,而不是在双精度上。
[注意] 在这里你要显式地测试do_something
私有方法。就您而言,您只需要测试公共方法,不应测试私有方法。因为如果使用私有方法的公共方法成功运行,那肯定意味着私有方法正在按预期工作。
所以为了确保你训练你的do_something
私有方法,你需要创建两个上下文:
context 'when anything is true' do
tests for call method goes here in this case
end
context 'when anything is false' do
tests for call method goes here
end
这意味着anything
,例如,如果一个模型确实model.save
确保在 save 方法上设置期望,因此在一个上下文中它返回false
导致do_method does
不会被执行。在其他情况下when true
,请确保您设置了一个期望以使其返回true
,以便您的do_something
方法被调用和执行,这隐含地意味着它得到了训练,如果在这种情况下调用测试通过,那肯定意味着它do_something
按预期工作。要了解有关测试私有方法的更多信息,您可以观看 Sandi Matz 的精彩演讲。
推荐阅读
- node.js - 可选择在开发环境中使用本地 npm 包
- list - 如何根据方案中另一个函数的评估递归地将元素添加到列表中
- c# - Automapper 与 VS2010 是 AutoMapper (逐字)
- vba - 如何在 .To 和 .Cc 中阻止发送到群组的电子邮件
- ios - iOS UITextField addTarget 和 textFieldDidEndEditing 的区别
- php - 如何在 Bootstrap WordPress 中添加 2 列博客文章
- php - Codeigniter 中的 PdfParser
- html - 如何将选定的选项插入到使用 API 中的选项的选择下拉列表中?
- wordpress - Wordpress 高级自定义字段重复器,子字段默认值
- excel - 在 Mac 上从 Excel 工作表中读取值