Skip to content

Instantly share code, notes, and snippets.

@gquemener
Created May 5, 2014 15:00
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gquemener/292e7c5a4bbb72fd48a8 to your computer and use it in GitHub Desktop.
Save gquemener/292e7c5a4bbb72fd48a8 to your computer and use it in GitHub Desktop.
Consecutive calls mocking /w phpspec
<?php
/**
* What I want to achieve
*/
class FooSpec
{
function it_does_stuff($collab)
{
$collab->doCollabStuf()->willReturn('foo'); // Returns foo the first time
$collab->doCollabStuf()->willReturn('bar'); // Returns bar the second time
// Returns null the third time
$this->doStuff()
}
}
/**
* What I usually do
*/
class FooSpec
{
function it_does_stuff($collab)
{
$returns = ['foo', 'bar']
$collab->doCollabStuf()->will(function() use (&$returns) {
return array_shift($returns);
});
$this->doStuff()
}
}
@jakzal
Copy link

jakzal commented May 5, 2014

<?php

/**
 * you could also do (not really better in this particular case)
 */
 class FooSpec
{
    function it_does_stuff($collab)
    {
        $collab->doCollabStuf()->will(function() use ($collab) {
            $collab->doCollabStuf()->willReturn('bar');

            return 'foo';
        });

        $this->doStuff()
    }
}

@stof
Copy link

stof commented May 5, 2014

ReturnPromise has a little gem hidden inside it (hidden because it is not documented anywhere AFAIK): it supports having multiple return values, which are returned one after the other (the last one being used after that if there is more calls):

<?php
$collab->doCollabStuf()->willReturn('foo', 'bar', null);

@everzet
Copy link

everzet commented May 5, 2014

You have a statefull object that mixes query and command in one message. That's considered an anti-pattern by Prophecy (and many OOP practitioners). But generally, such behaviour is representable by this block of code:

<?php
$collab->doCollabStuf()->will(function() {
    static $returns = ['foo', 'bar'];

    return array_shift($returns);
});

You have a small logic operating on a static state.

As any other anti-pattern, this one has a moments of usefulness. For example, when you're describing behaviour of RNG or methods that are full of side-effects by nature. For such limited cases, Prophecy has a hidden (by purpose) shortcut for the:

<?php
$randomizer->getRandomNumber()->will(function() {
    static $returns = ['foo', 'bar'];

    return array_shift($returns);
});

in form of:

<?php
$randomizer->getRandomNumber()->willReturn('foo', 'bar');

@everzet
Copy link

everzet commented May 5, 2014

@stof my last comment is the reason why it's not documented :)

@gquemener
Copy link
Author

Allright, thanks!

We won't use this feature too much, promise!

🍻

@everzet
Copy link

everzet commented May 5, 2014

@gquemener the general idea of CQRS is very simple - you have queries and commands. Query should always have same behaviour - called with the same arguments should always produce same result. The way to change your query behaviour is by using commands.

Prophecy is opinionated towards CQRS.

@gquemener
Copy link
Author

Thanks for the explanation @everzet.

However, I'm not sure to fully understand what you mean by "command", I've found an article of Martin Fowler about CQRS (http://martinfowler.com/bliki/CQRS.html).
I'll read it when I have enough time.

@docteurklein
Copy link

commands are things that permit to change state, while queries are here to read (eventually) current state.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment