[英]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.