Posted about 2 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.

To avoid that, simply define your constants on the example class:

Copy
describe Notifier do class self::TestRecord # ... end let(:record) { self.class::TestRecord.new } it { ... } 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. :)


Alternatively, you could say:

Copy
let(:test_record_class) do Class.new(ApplicationRecord) do # ... end end let(:record) { test_record_class.new }

But that felt awkward for some of us.

By refactoring problematic code and creating automated tests, makandra can vastly improve the maintainability of your Rails application.

Owner of this card:

Avatar
Arne Hartherz
Last edit:
about 2 years 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 cookies to improve usability and analyze traffic.
Accept or learn more