2

I want to provide a null value for all calls with an id >= 100 -- and a concrete Product instance with the captured id for all others:

    every { repoMock.findById(more(100, true)) } returns null
    every { repoMock.findById(capture(idSlot)) } answers { Product(idSlot.captured, "Sample Product", 1.99) }

However the first behaviour is ignored -- for id 1234 the mock returns a Product instance.

I know I can fix it by having an answers{..} block with an if -- but what's going on here? Is the capturing behaviour ruling out all other behaviours?

Tom
  • 1,965
  • 3
  • 25
  • 33

1 Answers1

1

It is not the capturing behaviour specifically, but simply the fact that the expression inside the second every matches the same (and more) cases as the first every does.

When you define some behaviour for a combination of a mock object and arguments, you override any previously defined behaviour for the same mock object and arguments. Since capture(idSlot) matches any argument, it does also match arguments >= 100, and therefore, it overrides the behaviour defined in the above line.

But, on the other hand, since the first every is indeed more specific than the second every, the desired behaviour can be achieved by switching the lines:

every { repoMock.findById(capture(idSlot)) } answers { Product(idSlot.captured, "Sample Product", 1.99) }
every { repoMock.findById(more(100, true)) } returns null

Then the second every overrides only the behaviour for a part of all combinations of repoMock and ids, that is, only the ones that are >= 100.

Karsten Gabriel
  • 3,115
  • 6
  • 19
  • Yeah that works... I had tried that but had a mistake somewhere else so was misled.. :) Thx! – Tom Jul 24 '23 at 18:43