Rspec期望接收特定的记录实例



我有一个具有属性age的Rails模型User

我想测试一下,有些代码会提醒25岁以上的用户。

我写了这个测试:

it 'sends an alert to users over 25' do
user_who_should_be_alerted = User.create(age: 26)
user_who_should_not_be_alerted = User.create(age: 19)
expect(user_who_should_be_alerted).to receive(:alert_user)
expect(user_who_should_not_be_alerted).not_to receive(:alert_user)
alert_users_over_25
end

当然,这不起作用,因为alert_users_over_25将通过查询数据库来创建新对象。它不会使用在测试中创建的。

我想到的最接近的是:

it 'sends an alert to users over 25' do
user_who_should_be_alerted = User.create(age: 26)
user_who_should_not_be_alerted = User.create(age: 19)
expect_any_instance_of(User).to receive(:alert_user).once
alert_users_over_25
end

这基本上是有效的,但我没有明确说明应该提醒哪个用户,所以如果它只通知user_who_should_not_be_alerted,它就可以通过。

我的另一个选择是创建一个19岁的用户,然后运行alert_users_over_25,并期望没有人收到警报。然后在另一个测试中创建一个26岁的用户,并期望相反的结果。不过,这似乎没有那么防弹,因为我没有测试当数据库中有多个用户时它是如何工作的。这似乎也不太清楚。我认为第一个测试了解了该方法应该比其他选项做得更好的地方。

我的问题是,实现这个测试的最干净的方法是什么,以确保alert_users_over_25会为26岁的用户调用alert_user,而不是为19岁的用户?

代码有两个职责,可以分别测试

  1. 了解哪些用户需要提醒
  2. 为这些用户调用alert_user

您可以为这两件事创建两种方法。假设User.alertable_users和User.alert_necessary_users.alert_necessary_users将调用alertable_users并为这些用户调用alert_User。

在第二种方法的测试用例中,您可以

allow(User).to_receive(:alertable_users) { [user_who_should_be_alerted] }
expect(user_who_should_be_alerted).to receive(:alert_user)

请注意,该结构已变得更加以单一责任原则为导向。如果alertable_user的逻辑从高于25的逻辑更改为其他逻辑,那么第二种方法的测试用例不会更改!

最新更新