rspec/rspec-mocks — Issue #102: ArgumentMatchers make it impossible to have lets with same name
Author: amarshall
Created: 2012-01-31 22:51:22+00:00
State: open

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