Wednesday, May 31, 2006
Use class methods for stubs
Since I believe in unit testing one concrete class at a time I frequently use stubs in my tests. These stubs always return the same value and are unimportant to the current test.
For example, assume you have an Employee class that contains check_email behavior.
For example, assume you have an Employee class that contains check_email behavior.
class EmployeeIn the above example Employee depends on cell_phone and laptop. When testing check_email you should have (at least) two tests, one for the case where @laptop.working? is true and one where it returns false. The second scenario (where @laptop.working? is false) is perfect for stub usage.
def initialize(cell_phone, laptop)
@cell_phone = cell_phone
@laptop = laptop
end
def check_email(user, password)
if @laptop.working?
@laptop.check_email(user, password)
else
@cell_phone.check_email(user, password)
end
end
end
class EmployeeTest < Test::Unit::TestCaseThe above test is correct; however, it can be slightly changed. Because of duck typing and the fact that stubs should always return a constant value it is possible to use class methods instead of instance methods. This relieves you from needing a new instance for each stub.
class StubLaptop
def working?
false
end
end
...
def test_when_laptop_is_not_working_cell_phone_is_used
# code for setting up a mock for cell_phone
employee = Employee.new(mock_cell_phone, StubLaptop.new)
employee.check_email('jay', 'password')
# code to verify mock
end
end
class EmployeeTest < Test::Unit::TestCase
class StubLaptop
def self.working?
false
end
end
...
def test_when_laptop_is_not_working_cell_phone_is_used
# code for setting up a mock for cell_phone
employee = Employee.new(mock_cell_phone, StubLaptop)
employee.check_email('jay', 'password')
# code to verify mock
end
end



