Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to include several modules in RSpec?

I am uncertain about the way of including several modules into RSpec, so let me describe my situation.

Under app/helpers I have two files with helpers, containing the modules ApplicationHelper and MailersHelper. Although these are view helpers, which I use in my views and mails, I also use some of their methods in my tests, so they must by accessible within a describe clause.

Under app/spec/mailers I also have a file, containing the module Helpers. This module contains methods, that are only to be used in the tests (mostly wrapper methods for long expectations).

Additionally I have the following code:

class Helpers
  include Singleton
  include ActionView::Helpers::UrlHelper
  include ActionView::Helpers::NumberHelper
end

def helper
  Helper.instance
end

It serves the purpose of making view helpers available in tests. Currently this code resides within the Helper module right before the wrapper methods, as they use the Helper.instance method.

I have three mailers, that I want to test. So how do I make all those things accessible in the tests?

Option 1

Use include directly under describe in each of the mailer specs like so:

require 'spec_helper'

describe MyMailer do
  include ApplicationHelper
  include MailersHelper
  include Helpers
  ...
end

Option 2

In the file helpers.rb I do this:

require 'spec_helper'

module Helpers
  include MailersHelper
  include ApplicationHelper
  ...

end

RSpec.configure { |c| c.include Helpers }

and in each mailer spec I use require_relative './helpers'

Option 3

Like above but instead of including ApplicationHelper and MailersHelper in Helpers, I do this:

RSpec.configure do |c| 
  c.include Helpers
  c.include ApplicationHelper
  c.include MailersHelper
end

What I am so confused about is:

  1. I do the RSpec.configure part in a separate file (helpers.rb), which I require_relative in my mailers specs. So this means these modules will be available only to my mailers specs, not to the whole suit, right? (As it would have been the case if I had done this in spec_helper.rb).

  2. What is the best practice of organizing methods, which are not view helpers, but are helpers shared between several classes (mostly Controllers or Mailers). How should they be named, where should they be put?

Constant autoloading is really a hard topic for me - sometimes you get a module/class directly available and you don't need to do anything (but this might depend on the exact naming of your file/module), sometimes you must require it or relative_require it, but you must be careful where exactly you do this, because otherwise it will become globally available, and sometimes you have a special way of including things like with RSpec.configure... oh, boy!

like image 690
Alexander Popov Avatar asked Jul 17 '14 07:07

Alexander Popov


1 Answers

This should be done in spec_helper.rb. You can conditionally include modules depending on the spec type.

RSpec.configure do |config|
  config.include MailersHelper, type: :mailer
end

Any spec in spec/mailers will now automatically include MailersHelper.

You can trigger this manually by doing

RSpec.describe FooConstant, type: :mailer do
  # ... etc
end

in cases where the spec doesn't reside in spec/mailers but you want to treat it like one.

like image 191
Adam Lassek Avatar answered Nov 16 '22 10:11

Adam Lassek