Использование rspec для тестирования побочных эффектов

В моей модели Passages У меня есть метод receives_damage:

def receives_damage
  self.damage += 1

  self.phrases.each do |phrase|

    if !phrase.blank && phrase.hit_points <= self.damage
      phrase.blank = true
      phrase.content = phrase.content.gsub(/./, "&nbsp;")

      phrase.save
    end
  end

  self.save
end

В моей модели спецификации для receives_damage Я имею:

it "it increases the damage by 1"

it "it blanks any phrases with few enough hitpoints"

Первая спецификация была достаточно простой для написания, но во втором случае я тестирую побочный эффект и не знаю, как это сделать.

Спасибо

г.

2 ответа

Решение

Я согласен с апноэ Passage слишком много знает о Phrase, Однако, так как вы спросили конкретно о данном примере, вы можете сделать это, установив состояние объекта:

it "blanks any phrases with few enough hitpoints"
  low_hp = 3.times.map{ create :phrase, hp: 1 } # Or however you create them
  high_hp = 2.times.map{ create :phrase, hp: 1_000_000 }

  passage.phrases = low_hp + high_hp  # Or however you can set this state

  passage.receives_damage

  expect(low_hp.map(&:content)).to match_array [".", ".", "."]
end

Я бы, вероятно, предложил написать лучший выбор соответствия для конца. Таким образом, вы могли бы правильно сказать что-то лучше, например:

expect{passage.receive_damage}.to blank_phrases low_hp

Первый рефакторинг, отрывок знает слишком много о фразе.

В проходе:

def receives_damage
  self.damage += 1

   phrases.each do |phrase|
     phrase.tap { |p| p.on_blank }.save if phrase.blankable?(damage)
   end

  save
end

В фразе:

def on_blank
  self.blank   = true
  self.content = content.gsub(/./, "&nbsp;")
end

def blankable?(damage)
  !blank && hit_points <= damage
end

Затем проверьте, получает ли объект фразы правильные методы.

Другие вопросы по тегам