由于mysql时间戳格式,我的rspec测试是否失败?

时间:2016-04-08 20:14:53

标签: mysql ruby-on-rails ruby rspec

我有一个失败的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_dateto_i的逻辑,以便找出days_in_limbo并设置发送电子邮件的条件:< / p>

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中的格式以便它和&# #39;传递可以由Rails格式化的信息。我不是在寻找逻辑的替代解决方案,例如修改我的cron作业或使用像whenevertimecop这样的宝石,但不管怎么说,如果这是你要建议的内容:)

2 个答案:

答案 0 :(得分:0)

并非100%确定所提供的信息,但我认为数据库的状态不会像您期望的那样在expect...change块内发生变化。在这种情况下,我也不认为使用subject是合适的。

我猜你是否用你subject的内容替换了let,你可能会通过测试。您也可以尝试使用let代替let!,因为let!将在示例之前运行。

答案 1 :(得分:0)

感谢所有评论/回复。该问题最终成为range变量,不包括我正在测试的created_at日期的评估。