Search code examples
rubyrspecinitializer

rspec Object.new does not invoke initialize correctly


module BusinessMath
  class Cashflows
    include Newton

    attr_accessor :cashflows

    def initialize(cashflows)
      @cashflows = rectify_cashflows(cashflows)
    end

    private

    def rectify_cashflows(cashflows)
      cashflows.sort_by! { |cashflow| cashflow[:date] }

      cashflows.each do |cashflow|
        cashflow[:delta] = 0 if cashflow[:date] == cashflows.first[:date]
        cashflow[:delta] = Date.range_360(cashflows.first[:date], cashflow[:date])
      end

      cashflows
    end
  end
end

# spec
before(:all) do
  @payload = [
    { date: Date.parse('1.1.2018'), amount: -100 },
    { date: Date.parse('1.6.2018'), amount: -50 },
    { date: Date.parse('1.1.2019'), amount: 150 }
   ]
end

describe '.initialize' do
  let(:object) { BusinessMath::Cashflows.new(@payload) }

  it 'sets @cashflows' do
    expect(object.cashflows).to eq(@payload)
  end
end

This test is supposed to fail since rectify_cashflows sorts the cashflows and adds a delta key in each cashflow. The expected and in console working .cashflow looks like this:

[
  { date: Date.parse('1.1.2018'), amount: -100, delta: 0 },
  { date: Date.parse('1.6.2018'), amount: -50, delta: 180},
  { date: Date.parse('1.1.2019'), amount: 150, delta: 360}
]

How could I test it the correct way?


Solution

  • This test should fail since rectify_cashflows sorts them and adds a delta key in each cashflow.

    Yes. The problem is, your rectify method affects @payload from your spec too. Because it's the very same array (containing the same hashes). Naturally, an object is equal to itself and your test passes.

    A simple fix would be to use copying sort instead of in-place sort!. Or, better, simply deep-copy the array in the initializer. (deep part is important)