Ruby on rails 如何使用RSpec中的allow方法模拟模块内控制器内的函数(模块>;控制器>;函数)
我正在尝试在RSpec中编写Ruby on rails 如何使用RSpec中的allow方法模拟模块内控制器内的函数(模块>;控制器>;函数),ruby-on-rails,ruby,rspec,rspec-rails,Ruby On Rails,Ruby,Rspec,Rspec Rails,我正在尝试在RSpec中编写allow方法。我的rails控制器是 module Users class ProfilesController < ApplicationController # Update user profile def update payload = { name: params[:user][:name],email: params[:user][:email]} response = send_request_t
allow
方法。我的rails控制器是
module Users
class ProfilesController < ApplicationController
# Update user profile
def update
payload = { name: params[:user][:name],email: params[:user][:email]}
response = send_request_to_update_in_company(payload)
if response['code'] == 200
if User.first.update(user_params)
render json: { message: "User successfully updated"}, status: :ok
else
head :unprocessable_entity
end
else
render json: { error: 'Error updating user in Company' },status: :unprocessable_entity
end
end
private
def send_request_to_update_in_comapny(payload)
response = Api::V1::CompanyRequestService.new(
payload: payload.merge(company_api_access_details),
url: 'customers/update_name_email',
request_method: Net::HTTP::Post
).call
JSON.parse(response.body)
end
end
end
我在终端中遇到以下错误
Users::ProfilesController does not implement: send_request_to_update_in_comapny
enter code here
有了allow_任意一个实例,我就能让代码正常工作。但是我如何使用allow实现它呢?是的,的
allow\u any\u instance\u有效,因为顾名思义,它允许用户::ProfilesController
的任何instance用模拟返回值响应实例方法向公司的
然而,你的线路
allow(Users::ProfilesController).to receive(:send_request_to_update_in_company)
正在告诉RSpec模拟名为的类方法将\u请求发送到\u company
中的\u update\u,该方法不存在。因此,您会看到这样的错误消息
你不会说你的测试在哪里,但是一般来说,不管它在哪里,测试或者删除一个私有方法都不是一个好主意
我倾向于创建一个mockApi::V1::CompanyRequestService
对象来返回一个伪响应,然后控制器代码可以按预期解析该响应并生成预期的JSON。比如说
mock_request = instance_double(Api::V1::CompanyRequestService)
allow(mock_request).to receive(:call).and_return('{"code": 500}')
allow(Api::V1::CompanyRequestService).to receive(:new).and_return(mock_request)
另一种方法可能是不使用您的服务,而是使用诸如VCR
或WebMock
之类的工具在网络层提供模拟的JSON值-您的代码可以认为它在向internet发出呼叫,但实际上它会返回您在测试中定义的响应。这样如何:
规格/请求/用户/配置文件\u控制器\u规格.rb
require 'rails_helper'
RSpec.describe "Users::ProfilesControllers", type: :request do
describe "Test call to special function: " do
let(:controller) { Users::ProfilesController.new }
it "Should response to code 500" do
response = controller.send_request_to_update_in_company("test")
expect(response).to eq({"code"=>"500", "test1"=>"abc", "test2"=>"def"})
end
it "Should return to true" do
response = controller.true_flag?
expect(response).to eq(true)
end
end
end
app/controllers/users/profiles\u controller.rb
module Users
class ProfilesController < ApplicationController
# Update user profile
def update
payload = { name: params[:user][:name],email: params[:user][:email]}
response = send_request_to_update_in_company(payload)
Rails.logger.debug "Ok71 = response['code'] = #{response['code']}"
# if response['code'] == 200
# if User.first.update(user_params)
# render json: { message: "User successfully updated"}, status: :ok
# else
# head :unprocessable_entity
# end
# else
# render json: { error: 'Error updating user in Company' },status: :unprocessable_entity
# end
end
# Not private, and not mistake to 'send_request_to_update_in_comapny'
def send_request_to_update_in_company(payload)
response = Api::V1::CompanyRequestService.new(
payload: "for_simple_payload_merge_values",
url: 'for_simple_customers/update_name_email',
request_method: "for_simple_request_method"
).call
Rails.logger.debug "Ok66 = Start to log response"
Rails.logger.debug response
JSON.parse(response.body)
end
# Simple function to test
def true_flag?
true
end
end
end
模块用户
类ProfilesController
app/services/api/v1/company\u request\u service.rb
class Api::V1::CompanyRequestService < ActionController::API
def initialize(payload="test1", url="test2", request_method="test3")
@payload = payload
@url = url
@request_method = request_method
end
def call
@object = Example.new
@object.body = {code: "500", test1: "abc", test2: "def"}.to_json
return @object
end
end
class Example
attr_accessor :body
def initialize(body={code: "000", test1: "init_value_abc", test2: "init_value_def"}.to_json)
@body = body
end
end
class Api::V1::CompanyRequestService
我使用简单的代码来模拟您的项目。修改它以适合您的工作环境!告诉我你的想法。谢谢大家!
class Api::V1::CompanyRequestService < ActionController::API
def initialize(payload="test1", url="test2", request_method="test3")
@payload = payload
@url = url
@request_method = request_method
end
def call
@object = Example.new
@object.body = {code: "500", test1: "abc", test2: "def"}.to_json
return @object
end
end
class Example
attr_accessor :body
def initialize(body={code: "000", test1: "init_value_abc", test2: "init_value_def"}.to_json)
@body = body
end
end