Skip to content

Instantly share code, notes, and snippets.

@cmaitchison
Forked from notahat/valid.rb
Created October 11, 2012 13:10
Show Gist options
  • Save cmaitchison/3872162 to your computer and use it in GitHub Desktop.
Save cmaitchison/3872162 to your computer and use it in GitHub Desktop.
Testing fail?
# By leaning hard on the declarative nature of let(), you get to use
# a pattern where there is a single shared example whose
# expected result is defined at a lower level in the code.
# It is not really a pattern that is intuitive to everyone when
# they read this sort of code for the first time, so I am not about
# to claim it is better than other approaches, only different.
# There is no need for explicit tests to assert that the correct
# arguments are passed to the validators in this example, because
# if the arguments are not correct the doubles will not return the
# stubbed values and the tests will fail. Dependency injection gets
# around the pesky stubbing of .new() on the collaborating validators.
class TopLevelValidator
def valid?(info, more_info, even_more_info)
validator_a.valid?(info, more_info) &&
validator_b.valid?(info, even_more_info)
end
def validator_a=(value)
@validator_a = value
end
def validator_b=(value)
@validator_b = value
end
private
def validator_a
@validator_a ||= ValidatorA.new
end
def validator_b
@validator_b ||= ValidatorB.new
end
end
describe TopLevelValidator do
let(:info) { stub }
let(:more_info) { stub }
let(:even_more_info) { stub }
let(:validator_a) do
double.tap do |validator|
validator.stub(:valid?).with(info, more_info){validator_a_result}
end
end
let(:validator_b) do
double.tap do |validator|
validator.stub(:valid?).with(info, even_more_info){validator_b_result}
end
end
let(:top_level_validator) do
TopLevelValidator.new.tap do |validator|
validator.validator_a = validator_a
validator.validator_b = validator_b
end
end
shared_examples_for 'a top level validator' do
it "validates correctly" do
top_level_validator.valid?(info, more_info, even_more_info).should == expected_result
end
end
context 'when validator_a is valid' do
let(:validator_a_result) { true }
context 'when validator_b is valid' do
let(:validator_b_result) { true }
let(:expected_result) { true }
it_behaves_like 'a top level validator'
end
context 'when validator_b is invalid' do
let(:validator_b_result) { false }
let(:expected_result) { false }
it_behaves_like 'a top level validator'
end
end
context 'when validator_a is invalid' do
let(:validator_a_result) { false }
context 'when validator_b is valid' do
let(:validator_b_result) { true }
let(:expected_result) { false }
it_behaves_like 'a top level validator'
end
context 'when validator_b is invalid' do
let(:validator_b_result) { false }
let(:expected_result) { false }
it_behaves_like 'a top level validator'
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment