Question

In my model Passages I have a method 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

In my model specs for receives_damage I have:

it "it increases the damage by 1"

it "it blanks any phrases with few enough hitpoints"

The first spec was easy enough to write, but in the second case I am testing a side-effect and I'm not sure how to do that.

Thanks

z.

Était-ce utile?

La solution

I agree with apneadiving your object Passage knows too much about Phrase. However, since you asked specifically about the given example, you can do it by setting up the object state:

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

I would probably suggest writing a better custom matcher for the end. That way you could properly say something better such as:

expect{passage.receive_damage}.to blank_phrases low_hp

Autres conseils

First refactor, passage knows too much about phrase.

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

Then check if phrase object receives the right methods.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top