Friday, March 13, 2015

Rails test helper for stubbing a constant

When Googling for how to mock or stub a constant in your Rails test suite, I found out about RSpec's stub_const method. I don't use RSpec though, so I wrote this.

The way I use it is to include it in ActiveSupport::TestCase somewhere in test/test_helper.rb.

class ActiveSupport::TestCase
  include WithStubbedConst
  ...
end
module WithStubbedConst
def with_stubbed_const(consts, scope=self.class)
stash = {}
consts.each_pair do |key, val|
stash[key] = scope.send(:remove_const, key)
scope.send(:const_set, key, val)
end
begin
yield
ensure
consts.each_pair do |key, val|
scope.send(:remove_const, key)
scope.send(:const_set, key, stash[key])
end
end
end
end
require 'test/unit'
require 'test_helper/with_stubbed_const'
class TestWithStubbedConst < Test::Unit::TestCase
include WithStubbedConst
module Bar
BAZ = 10
end
FOO = "foo"
def test_default_scope
assert_equal "foo", FOO
with_stubbed_const(:FOO => "changed!") { assert_equal "changed!", FOO }
assert_equal "foo", FOO
end
def test_specified_scope
assert_equal 10, Bar::BAZ
with_stubbed_const({:BAZ => 20}, Bar) { assert_equal 20, Bar::BAZ }
assert_equal 10, Bar::BAZ
end
def test_block_raises
assert_equal "foo", FOO
with_stubbed_const(:FOO => 99) { assert_equal 99, FOO; raise "boom" } rescue nil
assert_equal "foo", FOO
end
end