I've been trying to stub a private module method for the whole day now but with not progress.
Here is a snippet of my application controller class
class ApplicationController < ActionController::Base
include Cesid::Application
end
Cesid > Application.rb
module Cesid
module Application
extend ActiveSupport::Concern
included do
before_action :track_marketing_suite_cesid, only: [:new]
end
private
def track_marketing_suite_cesid
return unless id_token_available?
## @cesid_auth = Auth.new(@id_token)
@cesid_auth = Auth.new(id_token)
return unless @cesid_auth.present? && @cesid_auth.valid?
@cesid_admin = Admin.where(email: @cesid_auth.email).first_or_initialize
end
def id_token_available?
## @id_token.present?
id_token.present?
end
def id_token
@id_token ||= id_token_param
end
def id_token_param
cookies[:id_token]
end
end
end
Now, I'm trying to create a simple unit test for the method
id_token_available?
And I am just trying to set the id_token_param to a random value.
I've tried using this code as stated Is there a way to stub a method of an included module with Rspec?
allow_any_instance_of(Cesid).to receive(:id_token_param).and_return('hello')
but I just get this error
NoMethodError:
undefined method `allow_any_instance_of' for #<RSpec::ExampleGroups::CesidApplication::CesidAuthorizations::GetCesidApplication:0x00007fa3d200c1c0> Did you mean? allow_mass_assignment_of
Rspec file
require 'rails_helper'
describe Cesid::Application, :type => :controller do
describe 'cesid application' do
before do
allow_any_instance_of(ApplicationController).to receive(:id_token_param).and_return('hello')
end
it 'returns true if the id_token is present' do
expect(Cesid::Application.send('id_token_available?')).to eql(true)
end
end
end
Rspec version
3.5.4
This is honestly starting to drive me crazy
CodePudding user response:
I see three issues:
You call
allow_any_instance_of
in a context in which it is not defined.allow_any_instance_of
can be used inbefore
blocks. I need to see your RSpec code to be more specific.Actually your code is called on the
ApplicationController
, not on the module, therefore you need to change your stub toallow_any_instance_of(ApplicationController).to receive(:id_token_param).and_return('hello')
Currently
id_token_param
will not be called at all, becauseid_token_available?
checks the instance variable and not the return value of theid_token
method that calls theid_token_param
. Just change theid_token_available?
to:def id_token_available? id_token.present? end
CodePudding user response:
There's a much better way of going about this test. The type: :controller
metadata on your spec gives you an anonymous controller instance to work with.
Here's an example of how you could write this to actually test that the before_action
from your module is used:
describe Cesid::Application, type: :controller do
controller(ApplicationController) do
def new
render plain: 'Hello'
end
end
describe 'cesid before_action' do
before(:each) do
routes.draw { get 'new' => 'anonymous#new' }
cookies[:id_token] = id_token
allow(Auth).to receive(:new).with(id_token)
.and_return(instance_double(Auth, valid?: false))
get :new
end
context 'when id token is available' do
let(:id_token) { 'hello' }
it 'sets @cesid_auth' do
expect(assigns(:cesid_auth)).to be_present
end
end
context 'when id token is unavailable' do
let(:id_token) { '' }
it 'does not set @cesid_auth' do
expect(assigns(:cesid_auth)).to be_nil
end
end
end
end