我有一个 Rails 模型
User
具有一个属性 age
.
我想测试一些代码提醒任何超过 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 岁的用户而不是 19 岁的用户调用 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 以上更改为其他内容,那么您对第二种方法的测试用例不会改变!