我试图理解继承应用程序中的测试,我需要一些帮助 .
有很多像这样的规范组(视图规范):
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变量,而我正在重构它) .
现在,我认为在 before
块中使用 expect
是错误的 . 让我们暂时忘掉它 .
通常上面的测试是绿色的 .
但是,如果我 expect
行,则测试失败 . 在这种情况下, expect
似乎是在视图上存根方法 . 实际上,用 allow
替换 expect
似乎具有完全相同的效果 .
我认为正在发生的事情通常是 - 当与服务器一起运行时 - 视图将调用 job_posts
并且消息将落在控制器上的辅助方法上,这是预期的行为 .
但是,在这里, expect
正在设置期望值,同时在 view
上使用固定的返回值来存根方法 . 由于视图模板 will 调用该方法,测试通过 .
关于 expect
的意外"stub"副作用,我在rspec-mocks readme中发现了这个:
(...)我们还可以设置消息期望,以便在未调用find时示例失败:person = double(“person”)
期待(人) . 收到(:发现)
RSpec用它自己的类似测试的方法替换了我们正在存根或模拟的方法 . 在示例的最后,RSpec验证任何消息期望,然后恢复原始方法 .
有没有人对这种方法的具体使用有任何经验?
3 回答
好吧,这就是
expect().to receive()
的作用!这是rspec
的新的expectation syntax,它取代了should_receive
API相当于
此API设置期望值和返回值 . 这是默认行为 . 要实际调用原始方法,您需要明确说出:
关于其他一些问题:
let
API在rspec测试中非常普遍,并且在许多情况下可能比@instance变量更好(例如 - 它是懒惰的,因此它只在需要时运行,并且它被记忆,因此它最多运行一次) .allow
语法替换旧的rspec语法中的stub
方法,所以是的,它具有相同的效果,但不同的是,如果未调用stubbed方法,它将不会使测试失败 .正如OP要求的那样 - 有关should_receive的一些解释 - 单元测试预计会孤立运行 . 这意味着不应该测试不直接属于测试的所有内容 . 这意味着HTTP调用,IO读取,外部服务,其他模块等不是测试的一部分,并且出于测试的目的,您应该假设它们正常工作 .
您应该在测试中包含的是正确调用那些HTTP调用,IO读取和外部服务 . 为此,您设置 message expectations - 您希望测试的方法调用某个方法(其实际功能超出测试范围) . 所以你希望服务接收一个方法调用,使用正确的参数,一次或多次(你可以明确地预期它应被调用多少次),并且,作为交换它实际被调用,你存根它,并根据测试时,设置其返回值 .
Sources:
Message expectation
RSpec's New Expectation Syntax
如果您不希望存根作为副作用,则可以随时调用原始文件 .
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
Rspec是一个元宝石,它取决于rspec核心,rspec期望和rspec-mocks宝石 . Rspec-mocks是rspec的测试双重框架,支持对生成的测试双精度和真实对象的方法存根,伪造和消息期望 .
然而,是使用'方法存根'
是'消息期望'的使用
有关更多详细信息,请参阅Doc