Skip to content

Instantly share code, notes, and snippets.

@tomphp
Created January 2, 2014 11:39
Show Gist options
  • Save tomphp/8218012 to your computer and use it in GitHub Desktop.
Save tomphp/8218012 to your computer and use it in GitHub Desktop.
<?php
class TestClassSpec extends ObjectBehavior
{
public function it_runs_action1(ActionClass $action) {
$action->action1()->shouldBeCalled();
// I have to add this here even though it is not the focus of this test?
$action->action2()->shouldBeCalled();
$this->run($action);
}
public function it_runs_action2(ActionClass $action) {
$action->action2()->shouldBeCalled();
// I have to add this here even though it is not the focus of this test?
$action->action1()->shouldBeCalled();
$this->run($action);
}
}
@docteurklein
Copy link

I know it's a simplified example, but either your inline comments are wrong or the "it_" is wrong. Your code actally calls both action1 and action2. It makes sense to explicit it.

@tomphp
Copy link
Author

tomphp commented Jan 3, 2014

@docteurklein I'm not sure what you are saying is wrong? What I was trying to highlight was that in the TDD cycle you write the smallest possible failing test. In my contrived example this could be

public function it_runs_action1(ActionClass $action)
{
    $this->action1()->shouldBeCalled();

    $this->run($action);
}

This works fine and is simple to implement and get to pass by simply calling $action->action1();

Next you write the next failing tests, this again should be quite simple like so:

public function it_runs_action2(ActionClass $action)
{
    $this->action2()->shouldBeCalled();

    $this->run($action);
}

Again this reads well and you can see what is supposed to be happening but when you run it it fails with a message saying that in the second test action1() was called unexpectedly. The reason for this is once you set an expectation (I think Prophecy uses the term promise) any other calls are treated as being unexpected.

My issue was that I was then adding $this->action1()->shouldBeCalled(); to the 2nd test so it allows the other action to also be called in the method. My problem with that was I felt shouldBeCalled() was too strong since it's not the focus of the test, I just want to know that action2() was called.

After that has been done and the implementation is added the first test then fails with an unexpected action2() for exactly the same reason so something has to be added there also.

I got a reply on twitter from @everzet explaining that I could simply use willReturn() instead to allow the method to be called like so:

function it_runs_action2(ActionClass $action)
{
    $this->action1()->willReturn();

    $this->action2()->shouldBeCalled();

    $this->run($action);
}

This is better imho because it allows it to be called without say that it should be which is not a require of this particular test.

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