AR:BASE.default_timezone

I have a requirement to test code whose execution depends upon the
default_timezone setting. I have tried several approaches to this but
nothing that I do in my test seems to alter the behaviour that is set in
environment.rb.

Is there a way to dynamically alter AR’s method of storing datetime
during a test? Currently I attempt to do this in this fashion:

[ "local", "utc" ].each do |tz|
  ActiveRecord::Base.default_timezone = tz
  @my_mage = Magik.new
  @my_mage.description = tz
  @my_mage.my_time_local = DateTime.now
  @my_mage.my_time_utc = DateTime.now.utc
  @my_mage.save!
  puts @my_mage.description
end

but the contents of the my_time_local and my_time_utc do not seem to be
what I expect:

default_timezone = local
Local: Mon Feb 09 14:20:06 UTC 2009 = 1234189206.0 <- AR.my_time_local
now: Mon Feb 09 14:20:06 -0500 2009 = 1234207206.77585 <- Time.now
UTC: Mon Feb 09 19:20:06 UTC 2009 = 1234207206.0 <- AR.my_time.utc
now: Mon Feb 09 19:20:06 UTC 2009 = 1234207206.77609 <- Time.now.utc

default_timezone = utc
Local: Mon Feb 09 14:20:06 UTC 2009 = 1234189206.0 <- AR.my_time_local
now: Mon Feb 09 14:20:06 -0500 2009 = 1234207206.77807 <- Time.now
UTC: Mon Feb 09 19:20:06 UTC 2009 = 1234207206.0 <- AR.my_time.utc
now: Mon Feb 09 19:20:06 UTC 2009 = 1234207206.7783 <- Time.now.utc
.

Is it possible to override AR default_timezone values for testing?

What you really want to do is mock the default_timezone for the scope of
a particular test. For example,

require ‘mocha’

class MagikTest < ActiveSupport::TestCase
def test_something
tz = ‘Alaska’
ActiveRecord::Base.stubs(:default_timezone).returns(tz)
assert_equal tz, ActiveRecord::Base.default_timezone
end
end

This just shows you how the stubbing works; in practice, this test is
testing the Mocha library, and not your app. :slight_smile: The trick here is to
decide what you want the default_timezone call to return, and assign
that value to tz. Then every time you call AR::Base.default_timezone
during that test, you’ll get back the value of tz.

You’ll need to grab the mocha library first: gem install mocha

You can use this to test your app against multiple timezones to really
make sure it works.

Brent

James B. wrote:

I have a requirement to test code whose execution depends upon the
default_timezone setting. I have tried several approaches to this but
nothing that I do in my test seems to alter the behaviour that is set in
environment.rb.

Is there a way to dynamically alter AR’s method of storing datetime
during a test? Currently I attempt to do this in this fashion:

[ "local", "utc" ].each do |tz|
  ActiveRecord::Base.default_timezone = tz
  @my_mage = Magik.new
  @my_mage.description = tz
  @my_mage.my_time_local = DateTime.now
  @my_mage.my_time_utc = DateTime.now.utc
  @my_mage.save!
  puts @my_mage.description
end

but the contents of the my_time_local and my_time_utc do not seem to be
what I expect:

default_timezone = local
Local: Mon Feb 09 14:20:06 UTC 2009 = 1234189206.0 <- AR.my_time_local
now: Mon Feb 09 14:20:06 -0500 2009 = 1234207206.77585 <- Time.now
UTC: Mon Feb 09 19:20:06 UTC 2009 = 1234207206.0 <- AR.my_time.utc
now: Mon Feb 09 19:20:06 UTC 2009 = 1234207206.77609 <- Time.now.utc

default_timezone = utc
Local: Mon Feb 09 14:20:06 UTC 2009 = 1234189206.0 <- AR.my_time_local
now: Mon Feb 09 14:20:06 -0500 2009 = 1234207206.77807 <- Time.now
UTC: Mon Feb 09 19:20:06 UTC 2009 = 1234207206.0 <- AR.my_time.utc
now: Mon Feb 09 19:20:06 UTC 2009 = 1234207206.7783 <- Time.now.utc
.

Is it possible to override AR default_timezone values for testing?

in your test_helper:

require ‘mocha’

Then, in your test

def test_something
tz = :local
ActiveRecord::Base.expects(:default_timezone).returns(tz)
assert_equal tz, ActiveRecord::Base.default_timezone
end

The trick is to set tz to be whatever you want to get back from
AR::Base.default_timezone. If you use AR::Base.expects, then your
test will fail if AR::Base.default_timezone is called more than once
or not at all. If you don’t care how many times it gets called (i.e.,
if that’s not something you need to test), then use “AR::Base.stubs
(:default_timezone).returns(tz)” instead.

Brent

On Feb 9, 11:30 am, James B. [email protected]

Brent M. wrote:

in your test_helper:

require ‘mocha’

Then, in your test

def test_something
tz = :local
ActiveRecord::Base.expects(:default_timezone).returns(tz)
assert_equal tz, ActiveRecord::Base.default_timezone
end

The trick is to set tz to be whatever you want to get back from
AR::Base.default_timezone. If you use AR::Base.expects, then your
test will fail if AR::Base.default_timezone is called more than once
or not at all. If you don’t care how many times it gets called (i.e.,
if that’s not something you need to test), then use “AR::Base.stubs
(:default_timezone).returns(tz)” instead.

However, what I am testing is a library that actually modifies
ActiveRecord behaviour based on the default_timezone setting. So, it is
pointless to mock or stub what I am actually testing. I eventually just
overrode the environment setting in the test itself.

it “should set the UTC time (for _at/_on) correctly” do
ActiveRecord::Base.default_timezone = “utc”

end