jdune jdune - 1 year ago 58
Ruby Question

RSpec mocking module function of controller

So I'm very new to Rails and struggling a bit with RSpec, specifically mocking certain things. So I have a module (concern) that a few of my controllers are using. That module (ValidateAdmin) calls two other functions within, current_user and logged_in_user. To cover the most possibilities, I wanted to stub both those functions and set their return value. Any suggestions on how to make this work?

describe ValidateAdmin do
before :all do
class FakeController < ApplicationController
include ValidateAdmin
end
end

let(:controller) { FakeController.new }

describe '#validate_admin_logged_in' do
controller.stub(:current_user).and_return(instance_double(User, admin?: true))
controller.stub(:logged_in_user).and_return(instance_double(User, admin?: true))
[RSpec contexts go here]


Edit - Fixed it by containing my mocking statements inside a 'before' block. Also just realized stub is deprecated so switched to allow statements.

Answer Source

The controller instance can be stubbed like any other object. You may also need to add the route:

describe FakeController, type: :controller do
  let(:admin_user) { instance_double(User, admin?: true) }

  it "performs my excellent test" do
    allow(controller).to receive(:current_user).and_return(admin_user)
    routes.draw { get "custom_action" => "fake#custom_action" }
    get :custom_action
  end
end

let(:controller) is uneccessary -- RSpec does that for you. Also, the test class does not need to go into a before block -- it can simply be defined at the top of the file, or require-d.