4

In pure PHPUnit mocking I can do something like this:

$mock->expects($this->at(0))
    ->method('isReady')
    ->will($this->returnValue(false));

$mock->expects($this->at(1))
    ->method('isReady')
    ->will($this->returnValue(true));

I was not able to do the same thing using Prophecy. Is it possible?

Cœur
  • 37,241
  • 25
  • 195
  • 267
Marcelo
  • 1,702
  • 2
  • 24
  • 42

2 Answers2

11

You can use:

$mock->isReady()->willReturn(false, true);

Apparently it's not documented (see https://gist.github.com/gquemener/292e7c5a4bbb72fd48a8).

celtric
  • 154
  • 1
  • 6
  • Thanks! I cannot try it now but as soon as I can I will come back and mark it as resolved ;) – Marcelo Sep 25 '15 at 11:47
  • Relying on undocumented features is not a good move. There is a reason why they are not documented; and because they are not documented, they can change or even disappear without notice in a future version. In this particular case, as the discussion in the linked gist reveals, the feature you need is not implemented on purpose for a good reason. The purpose of `phpspec` is to help the developers create well-designed classes. http://techportal.inviqa.com/2014/09/11/my-top-ten-favourite-phpspec-limitations/ – axiac Feb 07 '16 at 15:45
  • Awesome :D Thank you – FosAvance Nov 28 '18 at 14:16
3

There is another documented way to do that. If you expect a different result on a second call, it means something has changed in between, and you probably used a setter to modify the object's state. This way you can tell your mock to return a specific result after calling a setter with specific argument.

$mock->isReady()->willReturn(false);

$mock->setIsReady(true)->will(function () {
    $this->isReady()->willReturn(true);
});

// OR

$mock->setIsReady(Argument::type('boolean'))->will(function ($args) {
    $this->isReady()->willReturn($args[0]);
});

More about it here https://github.com/phpspec/prophecy#method-prophecies-idempotency.

Alexander Guz
  • 1,334
  • 12
  • 31