Ruby on Rails - Rspec lanza ArgumentError con o sin argumentos

CorePress2024-01-24  9

Estoy intentando escribir una prueba bastante sencilla en un objeto de servicio que maneja un error. Rails versión 5.2 y Rspec 3.8.

aplicación/servicios/aplicación_servicio.rb

class ApplicationService
  def self.call(*args, &block)
    new(*args, &block).call
  end
end

aplicación/servicios/basic_objects/create_paid.rb

  module BasicObjects
    class CreatePayment < ApplicationService
      def initialize(args)
        @transaction_id = args[:transaction_id]
      end

      def call
        transaction = Transaction.find(@transaction_id)
        payment = Payment.new(transaction: transaction)
        payment.save
      rescue CustomError => e
        if /waiting/i === e.message
          puts "Ignoring exception \"#{e.message}\" to prevent retry"
        else
          raise e
        end
      end
    end

Aquí está la prueba

describe BasicObjects::CreatePayment, type: :model do
  describe '#call' do
    let(:params) { { transaction_id: "xyz" } }

    context 'when there is a rescued error' do
      before do
        allow_any_instance_of(Payment)
          .to receive(:save)
          .and_raise(CustomError, "waiting")
      end

      it 'does not raise an error' do
         expect { described_class.call(params) }.not_to raise_error
      end
    end
  end
end

Y responde con este error: No se esperaba ninguna excepción, obtuve #<ArgumentError: número incorrecto de argumentos (dado 1, esperado 0)

Pero si elimino los parámetros y en su lugar espero(described_class.call).not_to rise_error Me sale error por no enviar el argumento

<BasicObjects::CreatePayment (class)> received :call with unexpected arguments
         expected: ({:transaction_id=>"xyz"})
              got: (no args)

Entonces, elimino with(params) de la declaración de permiso

context 'when there is a rescued error' do
    before do
      allow(described_class).to receive(:call).and_raise(CustomError, "waiting")
    end

    it 'does not raise an error' do
       expect(described_class.call).not_to raise_error
    end
  end

Y obtengo

ArgumentError:
       wrong number of arguments (given 1, expected 0)

Cualquier ayuda es muy apreciada

ACTUALIZACIÓN He ajustado la llamada anterior para generar el error en una línea de la clase, en lugar der que simplemente llamar a la clase misma. Sin embargo, sigo recibiendo el mismo error: no se esperaba ninguna excepción, obtuve #<ArgumentError: número incorrecto de argumentos (dado 1, se esperaba 0)>

1

¿Estás reemplazando la llamada al método de la clase, no la de la instancia?

Cassandra S.

27/03/2021 a las 18:54

Lo llamo como se llama en la aplicación. ¿De qué otra manera lo hago?

-Carl

27/03/2021 a las 19:06



------------------------------------

Vaya, este fue un viaje confuso. Muy bien, recapitulemos:

Cuando escribes enable(described_class).toceived(:call).and_raise(...), estás diciendo que este método:

class ApplicationService
  def self.call(*args, &block)
    new(*args, &block).call
  end
end

debería generar el error. Cuando pruebas tu código localmente, eso es lo que realmente sucede.

Dado que la llamada de clase no es lo que se está probando, te sugiero que la pruebes así:

it 'does not raise an error' do
  dbl = class_double(Transaction)
  allow(dbl).to receive(:find).and_raise(CustomError, 'waiting')
  expect { described_class.new(params).call }.not_to raise_error
end

En realidad no puedes cortar elllamada al método de instancia, porque al hacerlo también eliminarás el rescate real que estás probando.

3

Gracias. Agregué ApplicationService a la publicación anterior, que implementa una llamada a un método de clase. Espero que eso aclare

-Carl

27/03/2021 a las 20:02

Lo siento, así es como espreguntó en el poste. En realidad, está todo en una sola línea.

-Carl

27/03/2021 a las 20:34

Muy bien, actualicé mi respuesta por última vez. Esto fue muy confuso, jajaja.

Cassandra S.

27/03/2021 a las 20:55



------------------------------------

Me encontré con un problema similar y apareció el mensaje <ArgumentError: número incorrecto de argumentos (dado 1, esperado 0)> fue muy engañoso y confuso.

Dado su ejemplo, el problemaEs probable que el método de inicialización de su clase CustomError tome 0 argumento y esté pasando el método de "espera" cadena como parte de tu simulacro, es decir. permitir_cualquier_instancia_de(Pago).to recibir(:guardar).and_raise(CustomError, "esperando").

El mensaje de error en realidad se queja de que está pasando una cantidad incorrecta de argumentos en su excepción cuando se genera la excepción simulada. Por lo tanto, esto debería solucionarse eliminando "esperando":

allow_any_instance_of(Payment)
  .to receive(:save)
  .and_raise(CustomError)

3

En realidad, no incluí toda la prueba;He actualizado la publicación anterior, para que puedas ver que la clase descrita está ahí

-Carl

27/03/2021 a las 19:17

Oh, genial, entonces ignora la última parte. He actualizado la respuesta, espero que ayude

- Pablo

27/03/2021 a las 19:38

De hecho, creo que estoy confundiendo aún más las cosas porque ApplicationService implementa una llamada a un método de clase. Actualizaré above

-Carl

27/03/2021 a las 19:52

Su guía para un futuro mejor - libreflare
Su guía para un futuro mejor - libreflare