简体   繁体   English

Rspec - Stub/allow_any_instance_of 包含的模块方法不起作用

[英]Rspec - Stub/allow_any_instance_of included module methods is not working

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这是我的应用程序的片段 controller class

class ApplicationController < ActionController::Base
   include Cesid::Application
end

Cesid > Application.rb 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? id_token_可用?

And I am just trying to set the id_token_param to a random value.我只是想将id_token_param设置为随机值。

I've tried using this code as stated Is there a way to stub a method of an included module with Rspec?我试过按照说明使用此代码有没有办法用 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 Rspec 档案

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 Rspec版

3.5.4

This is honestly starting to drive me crazy老实说,这让我发疯了

I see three issues:我看到三个问题:

  1. You call allow_any_instance_of in a context in which it is not defined.您在未定义的上下文中调用allow_any_instance_of allow_any_instance_of can be used in before blocks. allow_any_instance_of可以用在before块中。 I need to see your RSpec code to be more specific.我需要更具体地查看您的 RSpec 代码。

  2. Actually your code is called on the ApplicationController , not on the module, therefore you need to change your stub to实际上,您的代码是在ApplicationController上调用的,而不是在模块上调用的,因此您需要将存根更改为

    allow_any_instance_of(ApplicationController).to receive(:id_token_param).and_return('hello')
  3. Currently id_token_param will not be called at all, because id_token_available?目前根本不会调用id_token_param ,因为id_token_available? checks the instance variable and not the return value of the id_token method that calls the id_token_param .检查实例变量而不是调用id_token_paramid_token方法的返回值。 Just change the id_token_available?只需更改id_token_available? to:到:

    def id_token_available?定义 id_token_available? id_token.present? id_token.present? end结尾

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.规范中的type: :controller元数据为您提供了一个匿名的 controller实例供您使用。 Here's an example of how you could write this to actually test that the before_action from your module is used:这是一个示例,说明如何编写此代码以实际测试是否使用了模块中的before_action

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM