Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

318
Visualizações
RSpec: How to compare have_received arguments by object identity?

i used to using expect(subject/double).to haved_received(:a_method).with(args).exactly(n).times to test that a method be called with some specific arguments and be called exactly {n} times. But today it's broken with arguments are Comparable objects, take a look at the below code:

setup

class A; end

class B
 include Comparable
 attr_reader :val

 def initialize(val)
   @val = val
 end

 def <=>(other)
   self.val <=> other.val
 end
end

class S
 def call(x); end
end

s = S.new
allow(s).to receive(:call)

now the below test passed with normal object A

a1 = A.new
a2 = A.new

s.call(a1)
s.call(a2)

expect(s).to have_received(:call).with(a1).exactly(1).times
expect(s).to have_received(:call).with(a2).exactly(1).times

but it failed with Comparable object B

b1 = B.new(0)
b2 = B.new(0)

s.call(b1)
s.call(b2)

expect(s).to have_received(:call).with(b1).exactly(1).times
expect(s).to have_received(:call).with(b2).exactly(1).times

i debug and saw that the rspec matcher call the spaceship operator <=> to verify arguments, so it considers b1 and b2 are the same

Failure/Error: expect(s).to have_received(:call).with(b1).exactly(1).times
expected: 1 time with arguments:
received: 2 times with arguments:

What should i do to pass the test ?

over 4 years ago · Santiago Trujillo
2 Respostas
Responde à pergunta

0

This happens because Comparable implements ==, so your objects are treated as being equal in regards to ==:

b1 = B.new(0)
b2 = B.new(0)

b1 == b2 #=> true

To set a constraint based on object identity, you can use the equal matcher: (or its aliases an_object_equal_to / equal_to)

expect(s).to have_received(:call).with(an_object_equal_to(b1)).once

Under the hood, this matcher calls equal?:

b1 = B.new(0)
b2 = B.new(0)

b1.equal?(b2) #=> false
over 4 years ago · Santiago Trujillo Relatório

0

My solution: using the have_attributes matcher to check exactly object_id of the object argument

expect(s).to have_received(:call).with(have_attributes(object_id: b1.object_id))
.exactly(1).times

expect(s).to have_received(:call).with(have_attributes(object_id: b2.object_id))
.exactly(1).times
over 4 years ago · Santiago Trujillo Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda