簡體   English   中英

使用 Rspec 在 Ruby on Rails 中模擬單例類 [已解決]

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

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM