Skip to content

Commit 9d0738f

Browse files
author
Sam Phippen
committed
Warn if a fixture method is called from a before(:context) block.
Fixes #1442. The basic approach here is to capture the addition of the fixture methods to the example group instance and then monkeypatch them. The monkeypatch checks to see if we're currently in a before(:context) hook and if we are then it prints a warning and doesn't invoke the method. The warning here is a little sparse at the moment, and I'd like to make it more clear. One thing that's a little gross about this implementation is that it uses the inspect string of the example group to determine if we're in a before(:context) hook. As far as I can tell there isn't a better way to make that determination, but maybe someone's got a clever trick.
1 parent e27a461 commit 9d0738f

File tree

3 files changed

+53
-0
lines changed

3 files changed

+53
-0
lines changed

example_app_generator/generate_stuff.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ def setup_tasks
1414

1515
def final_tasks
1616
copy_file 'spec/verify_active_record_spec.rb'
17+
copy_file 'spec/verify_fixture_warning_spec.rb'
1718
run('bin/rake db:migrate')
1819
if ::Rails::VERSION::STRING.to_f < 4.1
1920
run('bin/rake db:migrate RAILS_ENV=test')
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
require 'rails_helper'
2+
3+
RSpec.describe "Fixture warnings" do
4+
5+
def generate_fixture_example_group(hook_type)
6+
RSpec.describe do
7+
include RSpec::Rails::RailsExampleGroup
8+
fixtures :things
9+
10+
before(hook_type) do
11+
things :a
12+
end
13+
14+
it "" do
15+
16+
end
17+
end
18+
end
19+
20+
it "Warns when a fixture call is made in a before :context call" do
21+
expect(RSpec).to receive(:warn_with).with(match(/Calling fixture method in before :context/))
22+
23+
generate_fixture_example_group(:context).run
24+
end
25+
26+
it "Does not warn when a fixture call is made in a before :each call" do
27+
expect(RSpec).not_to receive(:warn_with)
28+
29+
generate_fixture_example_group(:each).run
30+
end
31+
end

lib/rspec/rails/fixture_support.rb

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,27 @@ module FixtureSupport
2929
end
3030
self.use_instantiated_fixtures = RSpec.configuration.use_instantiated_fixtures
3131
fixtures RSpec.configuration.global_fixtures if RSpec.configuration.global_fixtures
32+
33+
def self.fixtures(*args)
34+
orig_methods = private_instance_methods
35+
super.tap {
36+
new_methods = private_instance_methods - orig_methods
37+
new_methods.each do |method_name|
38+
proxy_method_warning_if_called_in_before_context_scope(method_name)
39+
end
40+
}
41+
end
42+
43+
def self.proxy_method_warning_if_called_in_before_context_scope(method_name)
44+
orig_implementation = instance_method(method_name)
45+
define_method(method_name) do |*args, &blk|
46+
if self.inspect.include?("before(:context)")
47+
RSpec.warn_with("Calling fixture method in before :context ")
48+
else
49+
orig_implementation.bind(self).call(*args, &blk)
50+
end
51+
end
52+
end
3253
end
3354
end
3455
end

0 commit comments

Comments
 (0)