首页 文章

Rspec嘲讽,_748463_也可以将一个方法作为副作用?

提问于
浏览
9

我试图理解继承应用程序中的测试,我需要一些帮助 .

有很多像这样的规范组(视图规范):

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 回答

  • 21

    好吧,这就是 expect().to receive() 的作用!这是 rspec 的新的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变量更好(例如 - 它是懒惰的,因此它只在需要时运行,并且它被记忆,因此它最多运行一次) .

    事实上,用allow替换expect似乎具有完全相同的效果 .

    allow 语法替换旧的rspec语法中的 stub 方法,所以是的,它具有相同的效果,但不同的是,如果未调用stubbed方法,它将不会使测试失败 .


    正如OP要求的那样 - 有关should_receive的一些解释 - 单元测试预计会孤立运行 . 这意味着不应该测试不直接属于测试的所有内容 . 这意味着HTTP调用,IO读取,外部服务,其他模块等不是测试的一部分,并且出于测试的目的,您应该假设它们正常工作 .

    您应该在测试中包含的是正确调用那些HTTP调用,IO读取和外部服务 . 为此,您设置 message expectations - 您希望测试的方法调用某个方法(其实际功能超出测试范围) . 所以你希望服务接收一个方法调用,使用正确的参数,一次或多次(你可以明确地预期它应被调用多少次),并且,作为交换它实际被调用,你存根它,并根据测试时,设置其返回值 .

    Sources:

  • 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

  • 0

    Rspec是一个元宝石,它取决于rspec核心,rspec期望和rspec-mocks宝石 . Rspec-mocks是rspec的测试双重框架,支持对生成的测试双精度和真实对象的方法存根,伪造和消息期望 .

    allow().to receive
    

    然而,是使用'方法存根'

    expect().to receive
    

    是'消息期望'的使用

    有关更多详细信息,请参阅Doc

相关问题