Lasonic
Lasonic

Reputation: 901

Undefined local variable or method in Rspec test?

Here is my class

class Hero
  attr_reader :strength, :health, :actions

  def initialize(attr = {})
    @strength = attr.fetch(:strength, 3)
    @health = attr.fetch(:health, 10)
    @actions = attr.fetch(:actions, {})

    @dicepool = attr.fetch(:dicepool) 
  end

  def attack(monster)
    @dicepool.skill_check(strength, monster.toughness)
  end

end

And these are my tests

require 'spec_helper'
require_relative '../../lib/hero'

describe Hero do
  let(:dicepool) {double("dicepool")}

  describe "def attributes" do
    let(:hero){Hero.new dicepool: dicepool}

    it "has default strength equal to 3" do
      expect(hero.strength).to eq(3)
    end
    it "has default health equal to 10" do
      expect(hero.health).to eq(10)
    end

    it "can be initialized with custom strength" do
      hero = Hero.new strength: 3, dicepool: dicepool
      expect(hero.strength).to eq(3)
    end

    it "can be initialized with custom health" do
      hero = Hero.new health: 8, dicepool: dicepool
      expect(hero.health).to eq(8)
    end

    describe "attack actions" do
      let(:attack_action) {double("attack_action") }
      let(:hero) {Hero.new dicepool: double("dicepool"), actions: {attack: attack_action} }

      it "has attack action"
        expect(hero.actions[:attack]).to eq(attack_action)
      end
    end  


end

I keep on getting

in `block (3 levels) in ': undefined local variable or method 'hero' for RSpec::ExampleGroups::Hero::DefAttributes::AttackActions:Class (NameError)

and I don't know why. This is my first day of writing Rspec tests so please be nice...

Upvotes: 0

Views: 1615

Answers (2)

Jiří Pospíšil
Jiří Pospíšil

Reputation: 14402

You are not passing a block to the it method (you missing both do and end at the end).

 it "has attack action"
                        ^^^

The correct code should look like this:

describe Hero do
  let(:dicepool) {double("dicepool")}

  describe "def attributes" do
    let(:hero){Hero.new dicepool: dicepool}

    it "has default strength equal to 3" do
      expect(hero.strength).to eq(3)
    end
    it "has default health equal to 10" do
      expect(hero.health).to eq(10)
    end

    it "can be initialized with custom strength" do
      hero = Hero.new strength: 3, dicepool: dicepool
      expect(hero.strength).to eq(3)
    end

    it "can be initialized with custom health" do
      hero = Hero.new health: 8, dicepool: dicepool
      expect(hero.health).to eq(8)
    end

    describe "attack actions" do
      let(:attack_action) {double("attack_action") }
      let(:hero) {Hero.new dicepool: double("dicepool"), actions: {attack: attack_action} }

      it "has attack action" do
        expect(hero.actions[:attack]).to eq(attack_action)
      end
    end
  end
end

Upvotes: 0

Anthony
Anthony

Reputation: 15967

You have a typo in your last test, you forgot the word do:

  it "has attack action" do
    expect(hero.actions[:attack]).to eq(attack_action)
  end

Everything passes once added.

Upvotes: 1

Related Questions