Ruby on rails RSpec请求中stubing方法调用的正确方法
我试图在我的请求规范中删除一个:authenticate\u user方法调用,以便测试用户的关联创建。我使用这些博客文章作为存根的指南: (一) (二) 我在存根方面没有任何成功,我也不知道我错过了什么 当我试着Ruby on rails RSpec请求中stubing方法调用的正确方法,ruby-on-rails,rspec,stubbing,Ruby On Rails,Rspec,Stubbing,我试图在我的请求规范中删除一个:authenticate\u user方法调用,以便测试用户的关联创建。我使用这些博客文章作为存根的指南: (一) (二) 我在存根方面没有任何成功,我也不知道我错过了什么 当我试着 it 'creates a new contract' do allow(controller).to receive(:authenticate_user).and_return(user) post api_v1_user_contracts_path(u
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
我得到:
当我尝试时:
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
我得到
我的代码:
规范/请求/合同\u api\u规范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
app/controllers/api/v1/contracts\u controller.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
class Api::V1::ContractsController
app/controllers/concerns/token_authenticable.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
class NotAuthorizedException{render json:{error:'Not authorizedException'},status::unauthorized}从NotAuthorizedException中解救_
结束
私有的
def认证用户
@当前用户=DecodeAuthenticationCommand.call(请求.标题).结果
除非@current_user,否则引发NotAuthorizedException
结束
结束
其他问题:
1) 我应该使用一个真实的用户对象,还是应该是一个双重对象?我假设它应该是一个真正的用户,以便测试关联创建是否正常工作
2) 我是否应该使用allow(Api::V1::ContractsController)来接收(:验证用户)和返回(用户)?我以前试过,但不起作用,但我不知道是因为其他东西也破坏了它
感谢您提供的任何反馈 关键是
authenticate\u user
将用户分配给变量(稍后使用)。请尝试:
allow(DecodeAuthenticationCommand).to receive_message_chain(:call, :result).and_return(user)
使用双重测试时,您必须为用户定义所有方法,例如
合同
。另外,您正在检查合同是否已创建-在我看来,为用户使用真实对象是完全可以的
我刚刚尝试过,它可以工作,谢谢:)。我想我不能为用户使用双重测试,否则这个测试就没有意义了?我已经把我的评论移到了答案上,这对其他人来说会更好。谢谢,我不确定什么时候使用真正的对象才合适,你把它清除了。为什么不允许(Api::V1::ContractsController)。接收(:authenticate\u user).和_返回(用户)或允许(控制器)。到。。在此实例中工作?authenticate\u user
将user
分配给@current\u user
。稍后,在代码中使用@current\u user
。我认为您的代码将引发错误,因为@current\u user
将为零(contract=nil.contracts.build(contract\u params)
),而且authenticate\u user
实际上不会返回用户。成功时,它将返回nil
。所以和_return
是误导性的。@Derek抱歉,我不明白如果成功,为什么它实际上不会返回用户?