Created
February 16, 2011 10:13
-
-
Save jamesmartin/829140 to your computer and use it in GitHub Desktop.
Simplified illustrative example of 'collaboration' tests between two objects in RSpec
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Account | |
attr_writer :logger, :username, :password | |
def logger logger | |
@logger ||= logger | |
end | |
def login | |
# do authentication stuff... | |
begin | |
@logger.log('Invalid login') | |
rescue | |
# alternative logging | |
end | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
describe Account do | |
describe "logging account activity" do | |
context "when an invalid login attempt is made" do | |
it "logs the failed attempt" do | |
logger = double('Logger') | |
logger.should_receive(:log).with('Invalid login') | |
account = Account.new | |
account.logger = logger | |
account.username = 'invalid' | |
account.password = 'invalid' | |
account.login | |
end | |
end | |
context "when its logger encounters a problem" do | |
it "handles any errors raised" do | |
logger = double('Logger') | |
logger.stub(:log).and_raise "Logging unavailable" | |
account = Account.new | |
account.logger = logger | |
account.username = 'irrelevant' | |
account.password = 'irrelevant' | |
expect { account.login }.to_not raise_error | |
end | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
These tests focus on the collaboration between the
Account
andLogger
objects, from the perspective of theAccount
object. At the same time, we're defining an implicit contract betweenAccount
andLogger
, which we should test separately.The trick is to keep track of all the, as yet, unimplemented conditions of the contract between all collaborators as we design.
I find these kind of collaboration tests, involving test doubles, guide me towards a clearer separation of concerns and nicer interfaces.
What if RSpec could tell us whenever we use a test double without implementing and/or checking that the real object does what we expect?
Could the proposed Undefined method stub report help us here?