I am writing controller tests for an application that I did not build, so it's definitely been a learning process. This is my first time encountering a controller that inherits directly from AbstractController::Base. It does not behave, obviously, the same as other controllers.
Its format is roughly:
class SchwadGenericController < AbstractController::Base
def schwad_method var_one, var_two = nil, var_three = nil
if var_two.blank?
var_one.generic_method
end
render template: "schwad_templates/generic_template", layout: false
end
end
I tried normal testing, this is where I am currently at to get ANYTHING to happen.
require 'rails_helper'
describe SchwadGenericController do
# before(:each) do
# SchwadGenericController.skip_authorize_resource
# end
# login_user
let!(:variable){ create(:my_factory_variable) }
describe 'controller methods' do
it 'should hit this method' do
binding.pry
SchwadGenericController.schwad_method(variable)
# expect(response).to_render template: "schwad_templates/generic_template"
end
end
end
And here is roughly where my failures are landing.
Failures:
1) SchwadGenericController controller methods should hit this method
Failure/Error: Unable to find matching line from backtrace
NoMethodError:
undefined method `request=' for # <SchwadGenericController:0x007f8022db0a20>
I read up on abstract controllers and their role in rails here: https://www.mobomo.com/2012/06/and-you-thought-render-farms-were-just-for-pixar/
I read up on the docs here: http://api.rubyonrails.org/classes/AbstractController/Base.html
I would really appreciate another set of eyes on this and guidance as to how you guys have tested controllers and their methods, with controllers that are inheriting from AbstractController::Base.... What am I missing?
-Schwad
After some testing, I don't think this is possible. Controller specs are just wrappers for Rails functional tests which test classes inheriting from ActionController::Base
. For controller tests to even run, the controller must support the request
and response
objects, which is not the case of AbstractController::Base
(these are defined in ActionController::Base
). That is why you get the particular error when you run the test. For the same reason, you will not be able to use the controller spec helpers (expects) such as to_render
because, again, they are defined only for controller specs and your controller class is not a "controller" in the "controller specs" sense.
The only option you seem to have for testing is to test the controller just as any other plain ruby class. You'd need to move your test out of the spec/controllers
directory to some other, e.g. spec/abstract_controllers
and then you'd have to give up all controller spec helpers and test just calling the instance methods, e.g.:
describe 'controller methods' do
it 'should hit this method' do
c = SchwadGenericController.new
expect(c).to receive(:render).with(template: "schwad_templates/generic_template", layout: false)
c.schwad_method(variable)
end
end
Extending directly from AbstractController::Base seems the likely source of the error to me. Unless you're doing something very nonconventional there should be no reason to do this.
Are you sure you don't intend to inherit from ActionController::Base? There's a whole bunch of modules in ActionController required for rendering which is probably explains the error on a missing method in your tests.
If switching to ActionController::Base doesn't work. Try running app.get "/path/to/action"
from the rails console. Do you get the same error?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With