在关联模型中测试存根回调

发布于 2024-12-08 21:13:31 字数 572 浏览 0 评论 0原文

我有两个模型,通过简单的一对多关系链接。

class Device
  has_many :events

  def notify!
    (...)
  end
end

class Event
  after_create :notify_device
  belongs_to :device

  private

  def notify_device
    device.notify!
  end
end

Device#notify! 方法必须在测试中存根,因为在正常流程中它会触发与通过 RS-232 连接的设备的通信,这显然在测试环境中可能不可用(更不用说它不应该)测试中不会通知)。

我试图对 FactoryGirl 创建的 device 对象设置 should_receive 期望,但是 Event 类中使用的 device 方法返回不同的对象,它不知道该期望。

如何编写 rspec 测试来测试在正确的设备上调用 #notify! 的事实?

I have two models, linked by simple one-to-many relation.

class Device
  has_many :events

  def notify!
    (...)
  end
end

class Event
  after_create :notify_device
  belongs_to :device

  private

  def notify_device
    device.notify!
  end
end

Device#notify! method has to be stubbed in tests, as in normal flow it triggers communication with device linked via RS-232, which obviously may not be available in test environment (not to mention it shouldn't be notified in tests).

I was trying to set should_receive expectation on device object created by FactoryGirl, but device method used in Event class returns different object, which doesn't know about that expectation.

How to write rspec test that would test the fact that #notify! is called on proper device?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

月下客 2024-12-15 21:13:31

我不知道如何期待给定 AR 记录的消息。您可以将此功能添加到 rspec,或者添加一些记录器来通知!方法:

class Device

  def notify!(event)
    logger "Device with id '{self.id}' has been notified by event '#{event}'"
  end
end

在我看来,这样的记录器在生产中可能很有用,但在记录测试中,使用一些模拟,您可以将记录器交换为使用对象,您可以在测试中轻松检查并检查来自通知的消息。

I can't see how to expect message for given AR record. You can either add this feature to rspec, or maybe add some logger to notify! method:

class Device

  def notify!(event)
    logger "Device with id '{self.id}' has been notified by event '#{event}'"
  end
end

In my opinion such logger may be useful in production, but in test for logging use some mock that you can swap logger to use object you can easily examine in test and check message from notify.

烟织青萝梦 2024-12-15 21:13:31

如果您的测试中只有一个设备,那么使用 any_instance 应该没问题(因为应该编写良好的隔离测试)。

或者另一个选项是在设备上使用回调而不是事件:

class Device < ActiveRecord::Base
  has_many :events, :after_add => :notify!

  def notify!
    ...
  end
end

这应该更容易设置期望:

device = Device.new
device.should_receive(:notify!)
device.events << Event.create!

我刚刚想到(但没有尝试过)的另一个选项是存根活动记录用于获取设备的方法在事件创建期间。下面我猜测它只是 Device.find(device.id) 但它可能是其他东西。

device = Factory(:device)
device.should_receive(:notify!)
Device.stub(:find).with(device.id) { device }
Event.create!(:device => device)

Using any_instance should be fine if there is only one device in your test (as a good isolated test should be written).

Or another option is use a callback on Device instead of Event:

class Device < ActiveRecord::Base
  has_many :events, :after_add => :notify!

  def notify!
    ...
  end
end

That should be much easier to set expectations on:

device = Device.new
device.should_receive(:notify!)
device.events << Event.create!

Another option I just thought of (but haven't tried) is to stub out the method active record is using to fetch the device during event creation. Below i'm guessing it is just Device.find(device.id) but it might be something else.

device = Factory(:device)
device.should_receive(:notify!)
Device.stub(:find).with(device.id) { device }
Event.create!(:device => device)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文