Search code examples
ruby-on-railsrubyrspecruby-on-rails-5rspec-rails

Rails TimeHelpers travel_to with nanosecond not working


In my code I have Time.current.strftime('%Y%m%d%H%M%S%6N') and to test that I used the Rails TimeHelpers #travel_to method.

in the tests:

travel_to Time.local(2015, 2, 2, 11, 14, 30.123456) do
  ...
end

The problem is that Time.current.strftime('%Y%m%d%H%M%S%6N') returns 000000 for nanoseconds when it should be 123456.

Is there a work around? I am trying not to use TimeCop gem at the moment.


Solution

  • Unfortunately, Rails' travel_to truncates the value to seconds. From the docs:

    Note that the usec for the time passed will be set to 0 to prevent rounding errors with external services, like MySQL (which will round instead of floor, leading to off-by-one-second errors).

    As a workaround you could change your code to accept an explicit time with current time as its default:

    def your_method(time = Time.current)
      time.strftime('%Y%m%d%H%M%S%6N')
    end
    

    And in your tests:

    describe '#your_method' do
      context 'with an explicit time value' do
        let(:time) { Time.local(2015, 2, 2, 11, 14, 30.123456) }
    
        it 'generates the corresponding timestamp' do
          expect(your_method(time)).to eq('20150202111430123456')
        end
      end
    
      context 'without argument' do
        around do |example|
          travel_to(Time.local(2015, 2, 2, 11, 14)) { example.run }
        end
    
        it 'generates the current timestamp' do
          expect(your_method).to eq('20150202111400000000')
        end
      end
    end