Search code examples
rubyattr-accessor

ExpectationNotMetError, method returns nil


I am doing an online exercise. I am asked to create an InterestCalculator class that takes four arguments on initialization and defines two functions, amount and statement. I have to use the self method throughout the class. Instance variables should only be directly accessed in the initialize function and amount should only be calculated in one place.

Here are the specs:

describe InterestCalculator do
  before { @calc = InterestCalculator.new(500, 0.05, 4, 5) }

  describe "#amount" do
    it "calculates correctly" do
      expect( @calc.amount ).to eq(610.1)
    end
  end

  describe "#statement" do
    it "calls amount" do
      @calc.stub(:amount).and_return(100)
      expect( @calc.statement ).to eq("After 4 years I'll have 100 dollars!")
    end
  end
end

And here is my code:

class InterestCalculator
  attr_accessor :amount, :statement

  def initialize(principal, rate, years, times_compounded)
    @principal = principal
    @rate = rate
    @years = years
    @times_compounded = times_compounded
  end
  def self.amount
    amount = principal * (1 + rate / times_compounded) ** (times_compounded * years)
  end
  def self.statement
    statement = "After #{years} years i'll have #{amount} dollars"
  end
end

I keep getting the following error and don't know why:

RSpec::Expectations::ExpectationNotMetError

expected: 610.1
     got: nil

RSpec::Expectations::ExpectationNotMetError

expected: "After 4 years I'll have 100 dollars!"
     got: nil

Solution

  • If you intend amount and statement to be instance methods then change your code to

    def amount
      @amount ||= @principal * (1 + @rate / @times_compounded) ** (@times_compounded * @years)
    end
    
    def statement
      @statement ||= "After #{@years} years i'll have #{amount} dollars"
    end
    

    this is because

    def self.my_method
      # method body
    end
    

    creates a class method. Also, if you want amount and statement to be read-only change attr_accessor to attr_reader.