10

我正在尝试理解继承应用程序中的测试,我需要一些帮助。

有很多像这样的规范组(查看规范):

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视图上存根方法。实际上,替换expectallow似乎具有完全相同的效果。

我认为正在发生的事情通常是——当与服务器一起运行时——视图将调用job_posts并且消息将落在控制器上的辅助方法上,这是预期的行为。

然而,这里expect是设置一个期望值,同时在 stub 上view使用一个固定返回值的方法。由于视图模板调用该方法,因此测试通过。

关于意外的“存根”副作用expect,我在rspec-mocks 自述文件中发现了这一点:

(...) 我们还可以设置一个消息期望,以便在未调用 find 时示例失败:

person = double("person")
expect(Person).to receive(:find) { person }

RSpec用它自己的类似 test-double 的方法替换了我们正在存根或模拟的方法。在示例结束时,RSpec 验证任何消息期望,然后恢复原始方法。

有没有人对该方法的这种特定使用有任何经验?

4

3 回答 3

24

嗯,就是expect().to receive()这样!这是(不是这样)新的期望语法rspec它取代了should_receiveAPI

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 变量,而我正在重构它)。

letAPI 在 rspec 测试中非常普遍,并且在许多情况下可能比 @instance 变量更好(例如 - 它是惰性的,所以它只在需要时运行,并且它是记忆的,所以它最多运行一次)。

实际上,替换expectallow似乎具有完全相同的效果。

allow语法替换了旧 rspec 语法中的方法,所以是的,它具有相同的效果,但不同之处在于,如果调用stub存根方法,它不会使测试失败。


正如 OP 所要求的 - 一些关于should_receive单元测试的解释预计将单独运行。这意味着不直接包含在测试中的所有内容都不应进行测试。这意味着 HTTP 调用、IO 读取、外部服务、其他模块等不属于测试的一部分,出于测试的目的您应该假设它们正常工作。

应该在测试中包含的内容正确调用那些 HTTP 调用、IO 读取和外部服务。为此,您需要设置消息期望——您希望被测试的方法调用某个方法(其实际功能超出了测试的范围)。因此,您希望该服务接收一个带有正确参数的方法调用一次或多次(您可以明确地期望它应该被调用多少次),并且,作为实际调用它的交换,您将它存根,并根据进行测试,设置其返回值。

资料来源:

于 2014-03-26T20:14:39.320 回答
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

于 2017-05-28T18:02:22.663 回答
0

Rspec 是一个 meta-gem,它依赖于 rspec-core、rspec-expectations 和 rspec-mocks gems。Rspec-mocks 是一个用于 rspec 的测试替身框架,支持生成的测试替身和真实对象的方法存根、伪造和消息期望。

allow().to receive

是使用“方法存根”,但是

expect().to receive

是使用“消息期望”

您可以参考文档以获取更多详细信息

于 2014-12-20T13:00:14.193 回答