ArgumentMatchers make it impossible to have lets with same name
Created by: amarshall
As a result of the methods defined in RSpec::Mocks::ArgumentMatchers
, it is impossible to have a let()
with certain names. The most potentially devastating of which is boolean
. As anytime boolean
is referenced within the test, the method in RSpec::Mocks::ArgumentMatchers
is called, rather than referencing the let that was created. This can be seen by running the example tests below. This has all sorts of horrific ramifications, including false-passing tests and utter confusion, as it is non-obvious until you inspect the object itself that it is not the value you assigned it to.
I'm not sure what the "right" way to fix this is, or if it can be properly fixed, but at the least RSpec should raise an exception when "illegal" names are passed to let
, so the unexpected behavior is at least explicitly denied by RSpec.
class Example
def self.test(boolean)
boolean
end
end
shared_examples "example" do
context "and it is true" do
let(:value) { true }
it { should be_true }
it { subject.class.should == TrueClass }
end
context "and it is false" do
let(:value) { false }
it { should be_false }
it { subject.class.should == FalseClass }
end
context "and it is not defined" do
it "raises a NameError" do
expect { subject }.to raise_error(NameError)
end
end
end
describe Example do
describe "#test" do
# Passes for "bool" & "some_valid_name", fails for all others
%w[bool some_valid_name boolean any_args anything no_args duck_type hash_including].each do |name|
context "when variable is named #{name}" do
subject { Example.test(send(name.to_sym)) }
let(name.to_sym) { value }
include_examples "example"
end
end
end
end