Posted almost 5 years ago. Visible to the public. Repeats.

RSpec: How to define classes for specs

RSpec allows defining methods inside describe/context blocks which will only exist inside them.
However, classes (or any constants, for that matter) will not be affected by this. If you define them in your specs, they will exist globally. This is because of how RSpec works (short story: instance_eval).

Copy
describe Notifier do class TestRecord # ... end let(:record) { TestRecord.new } it { ... } end # TestRecord will exist here, outside of the spec!

This will come bite you at least when you try to define a class with the same name in another spec. Generally speaking, you don't want to pollute the global namespace in the first place.

Below you will find three examples how you can avoid polluting the global namespace. You can also read the Rubocop docs on LeakyConstantDeclaration Archive about this topic.

1. Defining the constant on the example class

Copy
describe Notifier do class self::TestRecord < ApplicationRecord # ... end it do expect(self.class::TestRecord.new).to be_a(ApplicationRecord) end end

Inside any let or it block, self will be the example's instance, so self.class points to the example class where TestRecord was defined. Basic Ruby.

2. Defining the class and assigning to a constant

Copy
describe Notifier do before do test_record = Class.new(ApplicationRecord) do # ... end stub_const('TestRecord', test_record) end it do expect(TestRecord.new).to be_a(ApplicationRecord) end end

3. Defining the class and assigning to a variable

Copy
describe Notifier do let(:test_record_class) do Class.new(ApplicationRecord) do # ... end end it do expect(test_record_class.new).to be_a(ApplicationRecord) end end

Each approach also works for Ruby modules, e.g. module self::TestModule < ParentModule; end or test_module = Module.new(ParentModule).

Your development team has a full backlog of feature requests, chores and refactoring coupled with deadlines? We are familiar with that. With our "DevOps as a Service" offering, we support developer teams with infrastructure and operations expertise.

Owner of this card:

Avatar
Arne Hartherz
Last edit:
4 months ago
by Arne Hartherz
Keywords:
local, locally, bleed
About this deck:
We are makandra and do test-driven, agile Ruby on Rails software development.
License for source code
Posted by Arne Hartherz to makandra dev
This website uses short-lived cookies to improve usability.
Accept or learn more