[英]Mock a singleton class In Ruby on Rails using Rspec [SOLVED]
嗨,我尝试为跟随类创建一个模拟:
module EstablishmentsQueryService
class << self
def find_by_id(id)
Establishment.find_by!(id:)
rescue ActiveRecord::RecordNotFound
raise EstablishmentNotFoundError.new id
end
end
end
尝试测试我的控制器
# frozen_string_literal: true
module Api
module V1
# Controllewr to manager Establishments
class EstablishmentsController < Api::V1::ApiController
before_action :validate_id, only: %i[destroy update show]
before_action :load_establishment, only: %i[destroy update show]
def show; end
def create
@establishment = Establishment.new(establishment_params)
@establishment = EstablishmentService.save(@establishment)
render status: :created
end
def destroy
EstablishmentService.delete(@establishment)
end
def update
@establishment.attributes = establishment_params
@establishment = EstablishmentService.save(@establishment)
end
private
def validate_id
message = I18n.t('establishment_controller.id.invalid', id: params[:id])
UuidValidateService.call(params[:id], message)
end
def load_establishment
@establishment = EstablishmentsQueryService.find_by_id(params[:id])
end
def establishment_params
params.require(:establishment).permit(:name, :cnpj, :description)
end
end
end
end
按照我的测试:
# frozen_string_literal: true
require 'rails_helper'
RSpec.describe 'Api::V1::Establishments', type: :request do
describe 'GET /api/v1/establishments/:id' do
context 'when has establishment' do
let(:establishment) { build(:establishment, id: p, created_at: DateTime.now, updated_at: DateTime.now) }
before do
allow_any_instance_of(EstablishmentsQueryService).to receive(:find_by_id).and_return(establishment)
get "/api/v1/establishments/#{establishment.id}"
end
it 'then http status is ok' do
expect_status_is_ok
end
it 'has body equal to expected' do
except_field_by_field(establishment, body_to_open_struct, %i[id name cnpj description])
end
end
context 'when has no establishment' do
before do
get "/api/v1/establishments/#{UUID.new.generate}"
end
it 'then http status is not_found' do
expect_status_is_not_found
end
end
context 'when use invalid id' do
before { get "/api/v1/establishments/#{FFaker::Lorem.word}" }
it 'then http status is bad_request' do
expect_status_is_bad_request
end
end
end
describe 'PUT /api/v1/establishments/:id' do
let(:establishments_query_service) { allow(EstablishmentsQueryService) }
let(:establishments_service) { allow(EstablishmentsService) }
context 'when updated with success' do
let(:establishment) { build(:establishment) }
let(:id) { UUID.new.generate }
before do
establishments_query_service.to receive(:find_by_id) { |p| build(:establishment, id: p, created_at: DateTime.now, updated_at: DateTime.now) }
establishments_service.to receive(:save) do |p|
to_return = p
to_return.created_at = DateTime.now
to_return.updated_at = DateTime.now
end
put "/api/v1/establishments/#{id}"
end
it 'then http status is ok' do
expect_status_is_ok
end
it 'has body equal to expected' do
actual = body_to_open_struct
except_field_by_field(establishment, actual, %i[name cnpj description])
expected(actual.id).to eq(id)
end
end
context 'when has no establishment' do
end
context 'when has constraint violation' do
end
end
describe 'DELETE /api/v1/establishments/:id' do
end
describe 'POST /api/v1/establishments' do
end
end
如果我使用 allow_any_instance_of 测试忽略配置,请使用真实配置并失败,因为没有数据存储。 如果我使用 double 我收到以下错误:
Api::V1::Establishments GET /api/v1/establishments/:id 当已建立然后 http 状态正常失败/错误:allow_any_instance_of(EstablishmentsQueryService).to receive(:find_by_id).and_return(establishment) EstablishmentsQueryService 没有实现# find_by_id
我认为现在是用户 allow_any_instance_of 因为这个配置是针对静态方法的,但是没有用
如何模拟我的课程来测试我的控制器? 我使用 Ruby 3.1.2、rails 7.0.3 和 rspec-rails 5.1.2 谢谢
我发现了我的问题,我忘记使用 with() 在我的配置文件中定义预期的参数
允许(EstablishmentsQueryService)。接收(:find_by_id) .with(建立.id) .and_return(建立)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.