Rspec 期望特定记录实例接收

问题描述 投票:0回答:1

我有一个 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

ruby-on-rails rspec
1个回答
0
投票

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

  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 以上更改为其他内容,那么您对第二种方法的测试用例不会改变!

© www.soinside.com 2019 - 2024. All rights reserved.