RSpec 请求中存根方法调用的正确方法
Correct way of stubbing method call in RSpec request
我试图在我的请求规范中删除一个 :authenticate_user 方法调用,以便我可以测试用户的关联创建。我使用这些博客文章作为存根指南:
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
我得到:
当我尝试时:
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
我得到了
我的代码:
spec/requests/contracts_api_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
app/controllers/api/v1/contracts_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
app/controllers/concerns/token_authenticatable.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) 我应该使用真正的用户对象,还是应该使用双精度对象?我假设它应该是真实用户,以便测试关联创建是否有效。
2) 我应该使用 allow(Api::V1::ContractsController).to receive(: authenticate_user).and_return(用户)?我以前试过但没有用,但我不知道这是因为其他东西也破坏了它。
感谢您提供任何反馈!
重点是 authenticate_user
将 user 分配给变量(稍后您会使用它)。请尝试:
allow(DecodeAuthenticationCommand).to receive_message_chain(:call, :result).and_return(user)
对于测试替身,您将必须为用户定义所有方法,例如contracts
。此外,您正在检查合同是否已创建 - 在我看来,为 user
.
使用真实对象完全没问题
我试图在我的请求规范中删除一个 :authenticate_user 方法调用,以便我可以测试用户的关联创建。我使用这些博客文章作为存根指南:
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
我得到:
当我尝试时:
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
我得到了
我的代码: spec/requests/contracts_api_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
app/controllers/api/v1/contracts_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
app/controllers/concerns/token_authenticatable.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) 我应该使用真正的用户对象,还是应该使用双精度对象?我假设它应该是真实用户,以便测试关联创建是否有效。
2) 我应该使用 allow(Api::V1::ContractsController).to receive(: authenticate_user).and_return(用户)?我以前试过但没有用,但我不知道这是因为其他东西也破坏了它。
感谢您提供任何反馈!
重点是 authenticate_user
将 user 分配给变量(稍后您会使用它)。请尝试:
allow(DecodeAuthenticationCommand).to receive_message_chain(:call, :result).and_return(user)
对于测试替身,您将必须为用户定义所有方法,例如contracts
。此外,您正在检查合同是否已创建 - 在我看来,为 user
.