Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rspec Controller testing in Rails a controller that inherits from AbstractController::Base

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

like image 518
Nick Schwaderer Avatar asked Mar 29 '16 14:03

Nick Schwaderer


2 Answers

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
like image 105
Matouš Borák Avatar answered Oct 13 '22 01:10

Matouš Borák


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?

like image 34
Anthony E Avatar answered Oct 13 '22 01:10

Anthony E