Testing Plugins | 93
class SslRequirementTest < Test::Unit::TestCase
def setup
@controller = SslRequirementController.new
@request = ActionController::TestRequest.new
@response = ActionController::TestResponse.new
end
# tests...
end
The Deadlock Retry plugin, another standard Rails plugin designed to retry dead-
locked database transactions, provides a good example of how to stub out an
ActiveRecord model class:*
class MockModel
def self.transaction(*objects, &block)
block.call
end
def self.logger
@logger ||= Logger.new(nil)
end
include DeadlockRetry
end
This allows simple features to be tested without introducing a database dependency:
def test_error_if_limit_exceeded
assert_raise(ActiveRecord::StatementInvalid) do
MockModel.transaction { raise ActiveRecord::StatementInvalid,
DEADLOCK_ERROR }
end
end
Testing Plugin Database Dependencies
The semantics of some plugins makes them difficult to test without relying on a data-
base. But while you would like your tests to run everywhere, you cannot depend on a
particular DBMS being installed. Additionally, you want to avoid requiring your
users to create a test database in order to test a plugin.
Scott Barron has come up with a clever solution, which he uses in his acts_asstate
machine plugin†(a plugin to assign states to ActiveRecord model objects, such as
pending, shipped, and refunded orders). The solution is to allow the user to test with
any DBMS, and fall back to SQLite (which is widely installed) if none is chosen.
- I would call this a stub, not a mock object, though some do not make the distinction. A stub tends to be
“dumb” and has no test-related logic—it only serves to reduce external dependencies. A mock is much
smarter and has knowledge of the test environment. It may keep track of its own state or know whether it is
“valid” with respect to the test cases that interact with it.
†http://elitists.textdriven.com/svn/plugins/acts_as_state_machine/trunk