【发布时间】:2016-04-08 20:14:52
【问题描述】:
我有一个 rspec 测试一直失败,我能想到的唯一可能导致问题的是测试生成的 created_at 格式是一个 mysql 时间戳,它没有被正确翻译成应用程序本身。这是我的reminders_spec.rb 测试,我从包含Reminders::LIMBO_EMAIL_INTERVAL_DAYS(设置为3)变量的数组中进行抽样,以确定created_at 日期是应该发送电子邮件的日期:
describe '#send_peer_shortage_notifications' do
subject { described_class.send_peer_shortage_notifications }
context 'minimum number of peer assessments not in pending/complete and limbo email interval day' do
limbo_interval_array = Array.new(10) { |i| i*Reminders::LIMBO_EMAIL_INTERVAL_DAYS }
let!(:evaluation) { create(:evaluation, created_at: (Evaluation::ASSESSMENTS_COMPLETION_WAIT_TIME + limbo_interval_array.sample.days).ago) }
let!(:assessments) do
create_list(:assessment,
Evaluation::MINIMUM_NUM_PEERS,
evaluation: evaluation,
state: [:expired, :declined].sample)
end
it 'sends limbo email' do
puts evaluation.created_at
expect { subject }.to change { ActionMailer::Base.deliveries.count }.by(1)
end
end
puts evaluation.created_at 的输出是 mysql 时间戳格式(即2016-04-01 19:44:43 UTC),它不响应像.to_date 这样的格式,我认为这可能导致我的测试失败。以下是失败信息:
Failures:
1) Reminders#send_peer_shortage_notifications minimum number of peer assessments not in pending/complete and limbo email interval day sends limbo email
Failure/Error: expect { subject }.to change { ActionMailer::Base.deliveries.count }.by(1)
expected result to have changed by 1, but was changed by 0
# ./spec/lib/reminders_spec.rb:110:in `block (4 levels) in <top (required)>'
这是reminders.rb 中的逻辑,我使用.to_date 和to_i 来计算days_in_limbo 并设置发送电子邮件的条件:
def self.send_peer_shortage_notifications
time = Time.current - Evaluation::ASSESSMENTS_COMPLETION_WAIT_TIME
range = time..Time.current
today = Time.current.to_date
evaluations = Evaluation.arel_table
assessments = Assessment.arel_table
left_join = evaluations
.join(assessments, Arel::Nodes::OuterJoin)
.on(evaluations[:id].eq(assessments[:evaluation_id]),
assessments[:state].in([:pending, :complete]),
assessments[:assessor_id].not_in([evaluations[:user_id],
evaluations[:manager_id]]))
.join_sources
relation = Evaluation
.in_process
.joins(left_join)
.where(created_at: range)
.group(:user_id)
.having(evaluations[:user_id].count.lt(Evaluation::MINIMUM_NUM_PEERS))
relation.find_each do |evaluation|
days_in_limbo = (today - (evaluation.created_at + Evaluation::ASSESSMENTS_COMPLETION_WAIT_TIME).to_date).to_i
if days_in_limbo > 0 && days_in_limbo % Reminders::LIMBO_EMAIL_INTERVAL_DAYS == 0
EvaluationMailer.delay.limbo_notification(evaluation)
end
end
end
注意:我只是想知道为什么这个测试没有通过,无论是由于格式化还是其他原因,以及是否有办法转换 rspec 中的格式,以便它传递的信息可以是由 Rails 格式化。我不是在寻找逻辑的替代解决方案,例如修改我的 cron 作业或使用像 whenever 或 timecop 这样的 gem,但无论如何,如果你要建议的话,谢谢:)
【问题讨论】:
-
你的 rspec 错误是什么?
-
对不起...应该包括那个!
Failures: 1) Reminders#send_peer_shortage_notifications minimum number of peer assessments not in pending/complete and limbo email interval day sends limbo email Failure/Error: expect { subject }.to change { ActionMailer::Base.deliveries.count }.by(1) expected result to have changed by 1, but was changed by 0 # ./spec/lib/reminders_spec.rb:110:in block (4 levels) in <top (required)>' -
更好的编辑问题)
-
另外,在您的
subject中包含部分代码 -
您的问题中有很多不相关的内容 - 尝试缩小范围。例如,可能是电子邮件数量没有改变,因为您的测试环境正在排队要由 sidekiq/延迟作业发送的电子邮件,或者可能是查询没有返回结果,或者可能是您在find_each 块总是返回 false。找出其中发生了哪一个,然后你就可以大大减少你的问题。
标签: mysql ruby-on-rails ruby rspec