我试图理解继承应用中的测试,我需要一些帮助。
有很多像这样的规范组(视图规范):
let(:job_post) { FactoryGirl.create(:job_post) }
# ...
before do
expect(view).to receive(:job_post).at_least(:once).and_return(job_post)
end
it "should render without error" do
render
end
... job_post
是控制器上定义的辅助方法。 (是的,他们可以使用@instance变量,而我正在重构它)。
现在,我认为在expect
块中使用before
是错误的。让我们暂时忘掉这一点。
通常上面的测试是绿色的
但是,如果我删除 expect
行,则测试失败。看来在这种情况下expect
正在查看视图上的方法。事实上,将expect
替换为allow
似乎具有完全相同的效果。
我认为正在发生的事情通常是 - 当与服务器一起运行时 - 视图将调用job_posts
并且消息将登陆上的辅助方法控制器,这是预期的行为。
但是,expect
设置了一个期望值,同时在view
上使用固定的返回值来存根方法。由于视图模板将调用该方法,因此测试通过。
关于那个意外的"存根" expect
的副作用,我在rspec-mocks readme:
(...)我们还可以设置消息期望,以便在未调用find时示例失败:
person = double("person") expect(Person).to receive(:find) { person }
RSpec 用我们自己的类似测试方法取代了我们正在抄写或嘲笑的方法。在示例的最后,RSpec验证任何消息期望,然后恢复原始方法。
有没有人对该方法的这种特定用途有任何经验?
答案 0 :(得分:21)
嗯,这就是expect().to receive()
的作用!这是rspec
的{{1}}新expectation syntax,取代了should_receive
API
expect(view).to receive(:job_post).at_least(:once).and_return(job_post)
相当于
view.should_receive(:job_post).at_least(:once).and_return(job_post)
此API将期望和设置为返回值。这是默认行为。要实际调用原始方法,您需要明确说出:
view.should_receive(:job_post).at_least(:once).and_call_original
关于其他一些问题:
(是的,他们本可以使用@instance变量,而我正在重构它)。
let
API在rspec测试中非常普遍,并且在许多情况下可能比@instance变量更好(例如 - 它是懒惰的,所以它只在需要时运行,并且它被记忆,因此它运行最多一次)。
事实上,将
expect
替换为allow
似乎具有完全相同的效果。
allow
语法替换了旧的rspec语法中的stub
方法,所以是的,它具有相同的效果,但不同的是,如果存根方法不会使测试失败是不被调用。
正如OP所要求的那样 - 关于should_receive
的一些解释 - 单元测试预计将单独运行 。这意味着不应该测试不是直接部分测试的所有内容。这意味着HTTP调用,IO读取,外部服务,其他模块等不是测试的一部分,并且出于 测试的目的,您应该假设他们工作正常。
在测试中应包含的内容是正确调用那些HTTP调用,IO读取和外部服务 。为此,您设置消息期望 - 您期望测试方法调用某种方法(其实际功能超出了考试)。因此,期望服务接收方法调用,使用正确的参数,一次或多次(您可以明确地预期应该调用多少次),以及以换取它实际被调用,你存根它,并根据测试,设置它的返回值。
<强>来源:强>
答案 1 :(得分:1)
如果您不想将存根视为副作用,则可以随时调用原始照片。
https://relishapp.com/rspec/rspec-mocks/v/2-14/docs/message-expectations/calling-the-original-method
例如我曾经想要监视一个方法,但也调用函数,否则它有其他方面的影响。这确实有帮助。
https://relishapp.com/rspec/rspec-mocks/v/2-14/docs/message-expectations/calling-the-original-method
答案 2 :(得分:0)
Rspec是一个元宝石,它依赖于rspec核心,rspec期望和rspec-mocks宝石。 Rspec-mocks是rspec的测试双重框架,支持对生成的测试双精度和真实对象的方法存根,假货和消息期望。
allow().to receive
是使用&#39; Method Stubs&#39;但是
expect().to receive
是使用&#39;消息期望&#39;
您可以参考Doc了解更多详情