使用rspec测试副作用

时间:2013-05-22 05:36:13

标签: ruby-on-rails rspec side-effects

在我的模型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 个答案:

答案 0 :(得分:2)

我同意apneadiving您的对象PassagePhrase了解太多。但是,由于您具体询问了给定示例,因此可以通过设置对象状态来执行此操作:

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

答案 1 :(得分:1)

第一个重构,段落对词组知之甚多。

In Passage:

def receives_damage
  self.damage += 1

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

  save
end

In Phrase:

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

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

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