【问题标题】:Is my rspec test failing because of mysql timestamp format?我的 rspec 测试是否因为 mysql 时间戳格式而失败?
【发布时间】: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_dateto_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 作业或使用像 whenevertimecop 这样的 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 &lt;top (required)&gt;'
  • 更好的编辑问题)
  • 另外,在您的subject中包含部分代码
  • 您的问题中有很多不相关的内容 - 尝试缩小范围。例如,可能是电子邮件数量没有改变,因为您的测试环境正在排队要由 sidekiq/延迟作业发送的电子邮件,或者可能是查询没有返回结果,或者可能是您在find_each 块总是返回 false。找出其中发生了哪一个,然后你就可以大大减少你的问题。

标签: mysql ruby-on-rails ruby rspec


【解决方案1】:

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

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

【讨论】:

    【解决方案2】:

    感谢所有 cmets/响应。问题最终是range 变量不包括我正在测试的created_at 日期的评估。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-04-13
      • 1970-01-01
      • 2011-04-24
      • 1970-01-01
      相关资源
      最近更新 更多