1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105
|
Feature: Return value contracts
In order to be able to record the stubbed value, Bogus requires that the block you pass when stubbing is free of side effects and idempotent.
If it's not, the behavior of contract verification is not defined.
Background:
Given a file named "session_controller.rb" with:
"""ruby
class SessionController
def initialize(authentication_service)
@authentication_service = authentication_service
end
def create(params)
@authentication_service.authenticate(params[:login], params[:password])
:render_welcome
rescue
:render_error
end
end
"""
Given a file named "authentication_service.rb" with:
"""ruby
class AuthenticationService
def initialize(user_db)
@user_db = user_db
end
def authenticate(login, password)
unless @user_db[login] == Digest::SHA1.hexdigest(password)
raise WrongPassword
end
end
end
class WrongPassword < StandardError
end
"""
And a spec file named "session_controller_spec.rb" with:
"""ruby
require_relative 'session_controller'
require_relative 'authentication_service'
describe SessionController do
fake(:authentication_service)
let(:controller) { SessionController.new(authentication_service) }
it "logs in the user with valid data" do
stub(authentication_service).authenticate('foo', 'bar')
expect(controller.create(login: 'foo', password: 'bar')).to eq(:render_welcome)
end
it "fails with invalid data" do
stub(authentication_service).authenticate('baz', 'bar') { raise WrongPassword }
expect(controller.create(login: 'baz', password: 'bar')).to eq(:render_error)
end
end
"""
Scenario: Bogus makes sure that all the return values recorded by stubbing are also present in tests of the real object
Then spec file with following content should fail:
"""ruby
require_relative 'authentication_service'
describe AuthenticationService do
verify_contract(:authentication_service)
it "logs in the user" do
service = AuthenticationService.new('foo' => Digest::SHA1.hexdigest('bar'))
expect {
service.authenticate('foo', 'bar')
}.not_to raise_error
end
end
"""
Scenario: Bogus does not fail the tests if all the recorded values have been also recorded on the real object
Then spec file with following content should pass:
"""ruby
require_relative 'authentication_service'
describe AuthenticationService do
verify_contract(:authentication_service)
it "logs in the user" do
service = AuthenticationService.new('foo' => Digest::SHA1.hexdigest('bar'))
expect {
service.authenticate('foo', 'bar')
}.not_to raise_error
end
it "raises WrongPassword with incorrect credentials" do
service = AuthenticationService.new('foo' => Digest::SHA1.hexdigest('bar'))
expect {
service.authenticate('baz', 'bar')
}.to raise_error(WrongPassword)
end
end
"""
|