4

I have dealer.cars where a dealer has many cars. In my spec i want to stub dealer.cars.delete(car) to return false. However i cannot get this to work. I have currently tried:

allow_any_instance_of(Car).to receive(:delete).and_return(false)

expect(dealer.cars).to receive(:delete).with(car).and_return(false)

However in my code when running the spec it is still returning true.

b.herring
  • 563
  • 2
  • 18
  • Is `dealer.cars` returning `Car`? Figure out what `dealer.cars.class` is. – tadman Jul 27 '22 at 15:49
  • yes it is returning `Car` – b.herring Jul 27 '22 at 15:53
  • If this is a Rails association, it might report to be `Car` but actually be something else. Rails does some shenanigans to make it seem like `Car` but is, fundamentally, another thing entirely. – tadman Jul 27 '22 at 16:36
  • `dealer.cars` is not an instance of `Car`, and `expect(dealer.cars).to receive....` won't work, because each time you call `dealer.cars`, you're returning a *different object* - so the object you're stubbing isn't the same object that's being used in the code. – Tom Lord Jul 27 '22 at 16:57
  • What are you actually trying to achieve with this code? "I want to stub `dealer.cars.delete`" isn't a problem, it's a solution. Whilst there are some hacky ways you may get this to work, there may be an entirely different solution you're not considering -- because you're asking for help on a solution, instead of asking about the original problem. See: https://meta.stackexchange.com/a/66378/369864 – Tom Lord Jul 27 '22 at 16:59

1 Answers1

1

Assuming cars is a has_many association on the Dealer model then no, cars won't be returning an instance of Car, it'll be returning a collection instance of class Car::ActiveRecord_Associations_CollectionProxy - so if you wanted to use the allow_any_instance_of, then you'd need to use that.

But a much better way to mock a chain of calls is:

expect(dealer).to receive_message_chain(:cars, :delete) { false }
smathy
  • 26,283
  • 5
  • 48
  • 68