Manmeet
Manmeet

Reputation: 281

Undefined method error in rspec

I'm implementing a Calculator DSL that has calculate as a method with add, subtract, multiply and divide block within the the method. When I run the rspec test using 'rspec calculator_spec.rb' command, it gives me an undefined method error for 'calculate'. The error is as follows -

 1) Calculator Addition operation returns correct values for positive numbers
 Failure/Error: calculate do
 NoMethodError:
   undefined method `calculate' for #<RSpec::ExampleGroups::Calculator::AdditionOperation:0x00000101d14780>
 # ./calculator_spec.rb:16:in `block (3 levels) in <top (required)>'

How can I overcome this error?

In calculator.rb -

class Calculator
  attr_accessor :total
  def calculate(&block)
    self.total = 0
    instance_eval(&block)
    puts total
  end

  def add(number)
    self.total += number
  end

  def subtract(number)
    self.total -= number
  end

  def multiply(number)
    self.total *= number
  end

  def divide(number)
    self.total /= number
  end
end

In calculator_spec.rb -

require './calculator'

describe 'Calculator' do

  describe "Addition operation" do
    it "returns correct values for positive numbers" do
      expect(
          calculate do
            add 2
            add 2
          end
      ).to eq(4)
    end

    it "returns correct values for negative numbers" do
      expect(
          calculate do
            add -2
            add -2
          end
      ).to eq(-4)
    end

    it "returns correct values for positive and negative numbers" do
      expect(
          calculate do
            add 2
            add 10
            add -10
          end
      ).to eq(2)
    end
  end

  describe "Mixed operations" do
    it "returns correct values when mixing all operations" do
      expect(
          calculate do
            add 2
            add -2
            subtract -2
            multiply 10
            divide 10
          end
      ).to eq(2)
    end
  end
end

Upvotes: 0

Views: 1149

Answers (2)

Uri Agassi
Uri Agassi

Reputation: 37419

Change this line in your rspec:

describe 'Calculator' do

to

describe Calculator do

This will create an implicit subject of type Calculator.

Besides that:

  1. calculate always returns nil (which is what puts returns):

    def calculate(&block)
      self.total = 0
      instance_eval(&block)
      total # <- no puts
    end
    
  2. You need to call calculate on your subject, easiest fix to add a calculate method on your describe block:

    describe Calculator do
      def calculcate(&block)
        subject.calculate(&block)
      end
    
      describe "Addition operation" do
        # ...
    

Upvotes: 2

Arup Rakshit
Arup Rakshit

Reputation: 118289

I put the code in a file called test.rb file :-

#!/usr/bin/env ruby

class Calculator 
  attr_accessor :total

  def calculate(&block)
    self.total = 0
    instance_eval(&block)
    total
  end

  def add(number)
    self.total += number
  end

  def subtract(number)
    self.total -= number
  end

  def multiply(number)
    self.total *= number
  end

  def divide(number)
    self.total /= number
  end
end

Then created the below test_spec.rb file :-

require_relative "../test.rb"


describe 'Calculator' do

  describe "Addition operation" do

    let(:ob) { Calculator.new }

    it "returns correct values for positive numbers" do
      expect(
        ob.calculate do
          add 2
          add 2                    
        end  
      ).to eq(4)
    end

    it "returns correct values for negative numbers" do
      expect(
        ob.calculate do
          add -2
          add -2
        end  
      ).to eq(-4)
    end

    it "returns correct values for positive and negative numbers" do
      expect(
        ob.calculate do
          add 2
          add 10
          add -10                    
        end  
      ).to eq(2)
    end
  end

  describe "Mixed operations" do
    let(:ob) { Calculator.new }
    it "returns correct values when mixing all operations" do
      expect(
        ob.calculate do
          add 2
          add -2
          subtract -2
          multiply 10
          divide 10                    
        end  
      ).to eq(2)
    end
  end
end

Now run the code as :-

arup@linux-wzza:~/Ruby> rspec -f documentation

Calculator
  Addition operation
    returns correct values for positive numbers
    returns correct values for negative numbers
    returns correct values for positive and negative numbers
  Mixed operations
    returns correct values when mixing all operations

Finished in 0.00197 seconds (files took 0.17971 seconds to load)
4 examples, 0 failures

Your code was not working, as you were calling the method #calculate on wrong object. You have to call this method, on the Calculator class instance of-course, as you have defined Calculator#calculate.

Upvotes: 1

Related Questions