0

在我的模型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"

第一个规范很容易编写,但在第二种情况下,我正在测试一个副作用,我不知道该怎么做。

谢谢

z。

4

2 回答 2

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
于 2013-05-23T00:49:40.503 回答
1

第一次重构,段落对短语了解太多。

在段落中:

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

然后检查短语对象是否接收到正确的方法。

于 2013-05-22T08:57:32.460 回答