We have an app that has “extensions” that are built as rails engines.
Each engine needs some code in the controllers, which we solved as
“include this module, call a method”. In order to test it, though, we
don’t want to “copy” the test for how that works into each engine, so
the idea is to write the tests once, in ‘spec/lib/extensions_spec.rb’,
where we are testing the other stuff that’s common for all the
extensions (which are defined on lib/extensions.rb, thus the spec’s
location)
In order to do it, I’m declaring a ‘sample’ controller in the specs
(just include the module, call the method), and then writing a couple
specs for what we are doing. Problem is, I can’t get rspec to
understand that that example group is a controller example groups.
I have
class MyExampleController < ApplicationController
include Extensions::ControllerHelpers
call_awesome_method # this, among other things, defines an
instance method on the controller that I want to test
end
inside my spec, and after that I tried:
- describe(“controller helpers”, :type => :controller) {
controller_name “my_example”; … }
It complains about controller_name not being a method of this dynamic
subclass of ActiveSupport::TestCase.
After some time reading the source I figured that :type => :controller
pretty much just works for config.include/config.extend. So on to the
next thing:
- describe MyExampleController do…end # aka, duh, the obvious one.
It complained about @controller being nil. Ended up reading most of
action_controller/test_case, and rspec-rails, with no success.
-
move that outside the big top-level describe(Extensions). That at
least got the specs running, but they failed because @controller is
nil. Again. So “Ok, it’s not setting the controller class at any
point, let’s force it”, and I added the ‘controller_name …’ call
(also tried going low-level to calling
ActiveSupport::TestCase.tests(klass), but that didn’t work either.) -
move all that into it’s own file (maybe, for some reason which
wouldn’t make much sense, two different types of specs can’t live
together in the same file)
Nope, same errors.
- move the file into spec/controllers
Bang! It works. But it’s ugly that it’s there, because I’m just
testing something “related” to controllers. (Granted, writing a
controller spec isn’t the best idea ever for this, but it’s the
straightest way to get a controller instanced and that responds to all
the routing helpers – which is, in the end, what I need to call.)
Basically, I read a lot of source code for both rspec-rails and rails’
own testing code, trying to figure out a way around of this, and I’m
running out of options. An alternative would be to include the module
and call the method on a mock instead of a real controller – but
‘call_awesome_method’ actually does some stuff with the rails router,
and I really don’t want to start writing all those huge mocks for just
testing a simple method (since the 2.3.x router is definitely not
something that I would characterize as ‘overly testable’)
So the question is: is there a way I force rspec into saying this is
a controller spec, treat it as such when the describe block is not
defined on spec/controllers? And (Or) where does the relevant code to
decide if it’s a controller spec (i.e., it should subclass
ControllerExampleGroup) or otherwise live? I can manage to work my way
around from there
Sorry for the rant, it’s past 4am here and I’m not sure I can think
straight at this anymore (or that all of this makes much sense)
Cheers,
-foca