Rspec - 结合expect_any_instance_of和接收计数

Mat*_*Mat 10 rspec ruby-on-rails rspec-mocks

我需要验证我的类的任何实例都接收到某种方法,但我不关心是否有许多实例接收它(它们应该是).

我试过这样的:

expect_any_instance_of(MyClass).to receive(:my_method).at_least(:once)
Run Code Online (Sandbox Code Playgroud)

但显然,它只允许单个实例多次接收方法,但不允许不同的实例.

有没有办法实现这一目标?

mes*_*jah 9

这是rspec-mocks中的一个已知问题.从V3.4文档Any instance:

rspec-mocks API是为单个对象实例设计的,但此功能适用于整个对象类.结果,存在一些语义上令人困惑的边缘情况.例如,expect_any_instance_of(Widget).to receive(:name).twice目前尚不清楚特定实例是否需要两次接收名称,或者是否预期接收到两个名称.(这是前者.)

此外

使用此功能通常是一种设计气味.可能是您的测试试图做得太多,或者被测对象太复杂了.

您是否有任何方法可以重构您的测试或应用程序代码以避免"令人困惑的边缘情况"?也许通过构建测试双重并期望它接收消息?

  • 这并不总是意味着代码异味。有些可能已经从“MyClass.my_method”更改为“MyClass.new.my_method”,以使其更加面向对象并减少代码味道。 (2认同)

Gab*_*eal 9

如果你需要忍受代码气味,这个rspec-mocks Github问题提出了一个解决方案:

receive_count = 0
allow_any_instance_of(MyClass).to receive(:my_method) { receive_count += 1 }

# Code to test here.

expect(receive_count).to be > 0
Run Code Online (Sandbox Code Playgroud)

  • 晚了几年,但以防万一有人需要帮助。您可能仍在使用“expect_any_instance_of”,当进行第二次调用时,它会抛出该错误。您必须将其更改为“allow_any_instance_of”,它对调用次数没有期望 (3认同)