0

I am trying to unit test the following code:

require 'mongoid'

class Seller
  include Mongoid::Document

  field :updated_at, type: Time

  def update_updated_at
    updated_at = Time.now
    save
  end

end

Here is my attempt

describe Seller do

  describe 'update_updated_at' do

    it 'sets updated_at to Time.now' do
      now = Time.new(2013,10,14)
      seller = Seller.new
      mock(Time).now { now }
      mock(seller).updated_at= now
      mock(seller).save
      seller.update_updated_at
    end

  end

end

I am getting the following failure

updated_at=(2013-10-14 00:00:00 -0600)
Called 0 times.
Expected 1 times.
zhon
  • 1,610
  • 1
  • 22
  • 31

2 Answers2

1

Here is the native method which is updates record updated_at attribute to current time For example

seller = Seller.first
seller.touch # updated_at set to current time

To mock the Time class there is a gem timecop which is super easy to use and dead simple Time, DateTime mocking e.g

it 'sets updated_at to Time.now' do
    now = Time.new(2013,10,14)
    Timecop.freeze(now) do
      seller = Seller.new
      seller.save # 2013-10-14
      seller.touch # same time 2013-10-14
    end
end
hawk
  • 5,409
  • 2
  • 23
  • 29
1

There is no need to mock this. Think about what you're doing here: you're setting updated_at and persisting it to the database. It's generally a code smell to stub/mock #save -- you can trust that it's doing what it should, which is persist attributes to the database. So, call the method, reload the record, and then assert that updated_at is set to the current time (as of when you called the method).

Or, just use touch ;)

By the way this test failed because you used updated_at = Time.now; it would have passed if you'd used self.updated_at = Time.now.

Elliot Winkler
  • 2,336
  • 20
  • 17
  • 1
    This is a *unit test*. I don't want to hit my database in my unit tests. Mocking ```save``` ensures I am calling save without hitting the database. – zhon Oct 15 '13 at 14:41
  • +1 for solving the problem ```self.update_at = Time.now```. Thank you! – zhon Oct 15 '13 at 14:42