为什么我的单元测试在重构时失败了

时间:2017-08-24 13:23:40

标签: ruby-on-rails ruby unit-testing refactoring

我是铁轨上的红宝石新手。我试图将一些代码分解为方法并调用该方法,因为我想重用该算法。问题在于,当我这样做时,覆盖该方法的单元测试失败了。

业务逻辑是

    begin
      generate_identifier_ladok_proof
      puts Ladok.api.save_education_event(self, current_user)
    rescue => e
      logger.warn { "Approving EducationEvent(ID: #{id}) failed: #
      {e.message}\n\t#{e.backtrace.join("\n\t")}" }
      errors.add(:base, e.message)
      return false
    end

    def generate_identifier_ladok_proof
      # Generate a new identifier if event has no identifier
      generate_identifier if identifier.nil?

      # Change identifier if identifier already exists in Ladok
      # (assuming we only send education events to Ladok once and once only)
      count_no_of_attempts = 0
      while (Ladok.api.education_event_exists?(self) && count_no_of_attempts < 5)
        generate_identifier
        count_no_of_attempts += 1
      end
      if (Ladok.api.education_event_exists?(self))
        errors.add(:base,"Utbildningstillfället #{identifier} med ID #{id} finns redan i LADOK.
                    Fem försök att byta till ett ID som inte finns har misslyckats. Kontakta Studentavdelningen eller försök igen.")
      return false
      end
    end

并且失败的测试是

    def test_click_event_change_status_ready_for_review_should_fail_and_produce_warning
      event = education_events(:course_event_status_ready_for_review)
      post :save_education_event, :change_status => 'xyz', :event_id => event.id, :education_event => event.attributes
      assert_response :redirect
      assert_redirected_to :action => 'edit', :id => event.education.id
ee_in_db = EducationEvent.find(event.id)
      assert_not_nil flash[:warning], 'There are supposed to be warnings here!'
      assert_nil flash[:notice], 'Notice were found but not expected.'
      assert_not_nil ee_in_db.identifier, 'EducationEvent identifier is not supposed to be nil.'
      assert_equal EventStatus::READY_FOR_REVIEW, ee_in_db.status, "EducationEvent status is supposed to be READY_FOR_REVIEW, not #{ee_in_db.status}."
    end

在行

    assert_nil flash[:notice], 'Notice were found but not expected.'

令人困惑的部分是,当我跳过重构并使业务逻辑看起来像下面的

    begin
      # Generate a new identifier if event has no identifier
      generate_identifier if identifier.nil?

      # Change identifier if identifier already exists in Ladok
      # (assuming we only send education events to Ladok once and once only)
      count_no_of_attempts = 0
      while (Ladok.api.education_event_exists?(self) && count_no_of_attempts < 5)
        generate_identifier
        count_no_of_attempts += 1
      end
      if (Ladok.api.education_event_exists?(self))
        errors.add(:base,"Utbildningstillfället #{identifier} med ID #{id} finns redan i LADOK.
                    Fem försök att byta till ett ID som inte finns har misslyckats. Kontakta Studentavdelningen eller försök igen.")
      return false
      end
      puts Ladok.api.save_education_event(self, current_user)
    rescue => e
      logger.warn { "Approving EducationEvent(ID: #{id}) failed: #
      {e.message}\n\t#{e.backtrace.join("\n\t")}" }
      errors.add(:base, e.message)
      return false
    end

然后测试通过。我怀疑这里存在一些我不明白的范围问题。

1 个答案:

答案 0 :(得分:2)

您没有处理重构后的generate_identifier_ladok_proof的回复。

在原始代码中,您有:

  if (Ladok.api.education_event_exists?(self))
    errors.add(:base,"Utbildningstillfället #{identifier} med ID #{id} finns redan i LADOK.
                Fem försök att byta till ett ID som inte finns har misslyckats. Kontakta Studentavdelningen eller försök igen.")
    return false
  end
  puts Ladok.api.save_education_event(self, current_user)

因此,如果Ladok.api.education_event_exists?(self)为真,则您从未运行过save_education_event

但新代码在return false内有generate_identifier_ladok_proof,但您从未检查过返回值。

begin
  generate_identifier_ladok_proof
  puts Ladok.api.save_education_event(self, current_user)
rescue => e

所以你应该让generate_identifier_ladok_proof返回true或false,并检查它。

begin
  if !generate_identifier_ladok_proof
    return false
  end
  puts Ladok.api.save_education_event(self, current_user)
rescue => e
  logger.warn { "Approving EducationEvent(ID: #{id}) failed: #
  {e.message}\n\t#{e.backtrace.join("\n\t")}" }
  errors.add(:base, e.message)
  return false
end

def generate_identifier_ladok_proof
  # Generate a new identifier if event has no identifier
  generate_identifier if identifier.nil?

  # Change identifier if identifier already exists in Ladok
  # (assuming we only send education events to Ladok once and once only)
  count_no_of_attempts = 0
  while (Ladok.api.education_event_exists?(self) && count_no_of_attempts < 5)
    generate_identifier
    count_no_of_attempts += 1
  end
  if (Ladok.api.education_event_exists?(self))
    errors.add(:base,"Utbildningstillfället #{identifier} med ID #{id} finns redan i LADOK.
                Fem försök att byta till ett ID som inte finns har misslyckats. Kontakta Studentavdelningen eller försök igen.")
    return false # fail
  else
    return true # success
  end
end