Search code examples
ruby-on-railsrubyrspecrspec-rails

Trouble with Rspec for timestamp in hashes


To compare to hashdata we had this in our spec

it 'should return the rec_1 in page format' do
     expect(response_body_json).to eql(Preseneter.new(ActiveRecordObject).page)
end

Presenter is a class that will accept the ActiveRecordObject and respond with hash data in a particular format.

We then added updated_at with timestamp to the hash_data. In my code I have updated_at = Time.zone.now So the spec started failing because both the updated_at had difference of few seconds.

Tried stubbing Time.zone

it 'should return the rec_1 in page format' do
     allow(Time.zone).to receive(:now).and_return('hello')
     expect(response_body_json).to eql(Preseneter.new(ActiveRecordObject).page)
end

but now response_body_json.updated_at comes as 'hello' but still Right hand side comes with a timestamp

Where am I going wrong??? or is there any other better way to handle such scenarios?


Solution

  • Since you haven't shown how response_body_json nor Presenter#page are defined, I cannot really answer why your current attempt doesn't work.

    However, I can instead say that I would use a different approach.

    There are two standard ways to write tests like this:

    1. Freeze time.

    Assuming you're using a relatively up-to-date rails version, you can use use ActiveSupport::Testing::TimeHelpers#freeze_time somewhere in the test, e.g. something like:

    around do |example|
      freeze_time { example.run }
    end
    
    it 'should return the movie_1 in page format' do
      expect(response_body_json).to eql(Presenter.new(ActiveRecordObject).page)
    end
    

    If you're on an older rails version, you may need to use travel_to(Time.zone.now) instead.

    And if you're on a very old rails version (or a non-rails project!), which doesn't have this helper library, you can use timecop instead.

    1. Use a fuzzy matcher for timestamps (e.g. be_within). Something along the lines of:

    .

    it 'should return the movie_1 in page format' do
      expected_json = Presenter.new(ActiveRecordObject).page
      expect(response_body_json).to match(
        expected_json.merge(updated_at: be_within(3.seconds).of(Time.zone.now))
      )
    end