You are ok with
$sender->getBalance()->shouldBeCalled()->willReturn(5);
$sender->setBalance(0)->shouldBeCalled();
$this->moveFromSenderToReceiver($sender, $reciever, 5);
that's the correct approach as $sender
and $receiver
are two collaborators.
You need to stop and think: what my class does? if your answer is changing the balance of particular user, well I'm afraid that's not the correct answer(*).
A better one could be: the behavior of your class is to "send a message" or "pass the responsibility" to user saying that he needs to set a difference balance. You are perfectly safe here saying, ok, if I invoke that method on my class, setBalance
and getBalance
should be called (because that's what your class is supposed to do!).
If you want to check that a balance value is setted (or returned) correctly, you must create another spec class (that will spec your User
class) and perform all tests that will put you in a confident state with your code.
That way, if both test are green, then you can safely rely on what you have written.
Remember that PHPSpec is a BDD tool, not a TDD one, so you have to keep your focus on those kind of things: "what's the behavior of my class?" is THE question.
Just for completeness, think about external code that you don't own, such ORM o DBAL or whatever you could use to perform I/O operation with a database. Say that class you are testing describing needs to write values onto database: you will never check that actual data are written. What you will do, instead, is to check if methods calls (such write
, read
or whatever name they got) are invoked: if they are, you are ok with it as, hopefully, your library got its own test suites that perform checks on whatever is the interaction between their own code and database.
(*) That's not the correct answer as you're not directly call $user->amount = 0
. First, that's silly as amount
, hopefully, is a private member of User
class. So you're just passing the responsibility to someone else (User
class, where the logic should belong). Of course, at a higher level of abstraction, saying that your class changes the balance of a particular user is ok, here I needed this kind of separation just to focus reader's attention onto a different point of view that could really, really help to understand why PHPSpec is so restrictive for this kind of operation, if you make a comparison with other tools, like PHPUnit or whatever.