代码之家  ›  专栏  ›  技术社区  ›  MLZ

RSpec请求中存根方法调用的正确方法

  •  1
  • MLZ  · 技术社区  · 6 年前

    我试图在我的请求规范中删除:authenticate\u user方法调用,以便测试用户的关联创建。我将这些博客帖子用作存根指南:

    (1) https://8thlight.com/blog/mike-knepper/2014/07/01/stubbing-authentication-and-authorization-in-controller-specs.html

    (2) http://johnnyji.me/rspec/2015/06/18/stubbing-controller-instance-methods-in-rspec.html

    我在存根方面没有任何成功,我不知道我错过了什么。

    当我尝试的时候

    it 'creates a new contract' do
          allow(controller).to receive(:authenticate_user).and_return(user)
          post api_v1_user_contracts_path(user), { params: contract_params}
          expect(response).to have_http_status(200)
        end
    

    我得到: enter image description here

    当我尝试时:

    it 'creates a new contract' do
          allow_any_instance_of(controller).to receive(:authenticate_user).and_return(user)
          post api_v1_user_contracts_path(user), { params: contract_params}
          expect(response).to have_http_status(200)
        end
    

    我得到了 enter image description here

    我的代码: 规范/请求/合同\u api\u spec.rb

    require 'rails_helper'
    require 'pry'
    context "POST #create" do
        let (:user) { User.create(full_name: "Jason Bourne", email: "jbourne@test.com", password: "123456") }
        let (:contract_params) do
          {
            "contract[vendor]" => "Lebara",
            "contract[starts_on]" => "2018-12-12",
            "contract[ends_on]" => "2018-12-16",
            "contract[price]" => "15"
          }
        end
    
        it 'creates a new contract' do
          allow(controller).to receive(:authenticate_user).and_return(user)
    
          post api_v1_user_contracts_path(user), { params: contract_params}
          expect(response).to have_http_status(200)
        end
    

    应用程序/控制器/api/v1/contracts\u控制器。rb型

    class Api::V1::ContractsController < ApplicationController
      before_action :authenticate_user
    
      def show
        if @current_user.contracts.find_by(id: params[:id])
          render json: @current_user.contracts.find_by(id: params[:id])
        else
          render json: { error: "Contract not found"}, status: 400
        end
      end
    
      def create
        contract = @current_user.contracts.build(contract_params)
        if contract.save
          render json: contract
        else
          render json: { error: contract.errors }, status: 400
        end
      end
    

    应用程序/控制器/关注点/令牌\u可验证。rb型

    class NotAuthorizedException < StandardError; end
    
    module TokenAuthenticatable
      extend ActiveSupport::Concern
    
      included do
        attr_reader :current_user
    
        before_action :authenticate_user
    
        rescue_from NotAuthorizedException, with: -> { render json: { error: 'Not Authorized' }, status: :unauthorized }
      end
    
      private
    
      def authenticate_user
        @current_user = DecodeAuthenticationCommand.call(request.headers).result
        raise NotAuthorizedException unless @current_user
      end
    end
    

    其他问题:

    1) 我应该使用真实的用户对象,还是应该使用double?我假设它应该是一个真正的用户,以便测试关联创建是否正常工作。

    2) 我应该使用allow吗( Api::V1::ContractsController )。接收(:authenticate\u user)。and\u return(用户)?我以前试过,但没有成功,但我不知道这是因为其他东西也破坏了它。

    感谢您提供的任何反馈!

    1 回复  |  直到 6 年前
        1
  •  2
  •   MrShemek    6 年前

    关键是 authenticate_user 将用户分配给变量(稍后使用)。请尝试:

    allow(DecodeAuthenticationCommand).to receive_message_chain(:call, :result).and_return(user)
    

    使用双重测试,您必须为用户定义所有方法,例如 contracts 。此外,您正在检查合同是否已创建-在我看来,使用真实对象进行 user