title: Confused about PhpSpec stubs and mocks again
body: <p>I'm building a Laravel 5 application at the moment and have gotten myself confused about how to mock things in PhpSpec.</p>
  
  <p>I'm building a schedule times validator that requires the intended schedule to be checked against all current schedules and see if there's any overlap (events are not allowed to overlap).</p>
  
  <p>I need to pull in the schedules in question so I can test against them. At the moment it's a very basic whereBetween query, but it's going to get a lot more complicated as there'll be recurring schedules to check against as well.</p>
  
  <p>So here's my stripped down class. I really just want to test the doesNotOverlap function.</p>
  
  <pre><code>use App\Schedule;
  
  class ScheduleTimesValidator
  {
      protected $schedule;
  
      public function __construct(Schedule $schedule)
      {
          $this-&gt;schedule = $schedule;
      }
  
      public function doesNotOverlap($slug, $intended)
      {
          $schedules = $this-&gt;getSchedulesBetween($slug, $intended);
          if(empty($schedules)) return true;
  
          return false;
      }
  
      protected function getSchedulesBetween($slug, $intended)
      {
          // Casting to array to make testing a little easier
          return $this-&gt;schedule-&gt;whereIsRecurring(false)
                                  -&gt;ofChurch($slug)
                                  -&gt;whereBetween('start', [$intended['start'], $intended['end']])
                                  -&gt;get()-&gt;toArray();
      }
  </code></pre>
  
  <p>and here's my Spec</p>
  
  <pre><code>use PhpSpec\ObjectBehavior;
  use Prophecy\Argument;
  
  class ScheduleTimesValidatorSpec extends ObjectBehavior
  {
      protected $validIntended = [
          'start' =&gt; '2015-12-01 12:00:00',
          'end' =&gt; '2015-12-01 13:00:00'
      ];
  
      protected $churchNonRecurringSchedules = [
          ['start' =&gt; '2014-11-20 13:00:00', 'end' =&gt; '2014-11-21 14:00:00'],
          ['start' =&gt; '2014-11-23 10:36:07', 'end' =&gt; '2014-11-23 11:36:07'],
      ];
  
      function let($schedule)
      {
          $schedule-&gt;beADoubleOf('App\Schedule');
          $this-&gt;beConstructedWith($schedule);
      }
  
  
      function it_is_initializable()
      {
          $this-&gt;shouldHaveType('App\Validation\ScheduleTimesValidator');
      }
  
      function it_should_return_true_if_it_does_not_overlap($schedule)
      {
          // $schedule-&gt;any()-&gt;willReturn([]);
          // $schedule-&gt;whereIsRecurring()-&gt;shouldBeCalled();
          // $schedule-&gt;whereIsRecurring(false)-&gt;ofChurch()-&gt;whereBetween()-&gt;get()-&gt;toArray()-&gt;willReturn([]);
          // $schedule-&gt;willReturn([]);
          // $this-&gt;getSchedulesBetween('slug', $this-&gt;validIntended)-&gt;willReturn([]);
          $this-&gt;doesNotOverlap('slug', $this-&gt;validIntended)-&gt;shouldReturn(true);
      }
  
      // Tear Down
      function letgo() {}
  
  }
  </code></pre>
  
  <p>If I run it like that I get: </p>
  
  <pre><code>! it should return true if it does not overlap
      method 'Double\App\Schedule\P8::whereIsRecurring()' not found.
  </code></pre>
  
  <p>I tried (as you can see) various commented out things to mock what $schedule will return, but that doesn't seem to work.</p>
  
  <p>So I guess I want to mock the protected <code>getSchedulesBetween</code> method in the class, but doing things like <code>$this-&gt;getSchedulesBetween($arg, $arg)-&gt;willReturn(blah)</code> doesn't work.</p>
  
  <p>Do I need to pull getSchedulesBetween() out of the class and move it into another class and then mock that? Or do I need to push $this->schedule->blah into the doestNotOverlap method so I can mock what $schedule will return?</p>
  
  <p>I don't want to actually test the App\Schedule Laravel Model - I just want to mock what it's returning and will be hardcoding a variety of queries that will be run to get the different model results.</p>
  
  <p>End of a long day here so brain a little zonked.</p>
  
  <h2>Update 2014-10-23</h2>
  
  <p>So I created a scope on my Schedule model</p>
  
  <pre><code>public function scopeSchedulesBetween($query, $slug, $intended)
  {
      return $query-&gt;whereIsRecurring(false)
                      -&gt;ofChurch($slug)
                      -&gt;whereBetween('start', [$intended['start'], $intended['end']]);
  }
  </code></pre>
  
  <p>Then created a new App\Helpers\ScheduleQueryHelper which instantiated App\Schedule as a variable and added this method:</p>
  
  <pre><code>public function getSchedulesBetween($slug, $intended)
  {
      return $this-&gt;schedule-&gt;schedulesBetween($slug, $intended)-&gt;get()-&gt;toArray();
  }
  </code></pre>
  
  <p>Then updated my spec to do</p>
  
  <pre><code>function let($scheduleQueryHelper)
  {
      $scheduleQueryHelper-&gt;beADoubleOf('App\Helpers\ScheduleQueryHelper');
      $this-&gt;beConstructedWith($scheduleQueryHelper);
  }
  
  function it_should_return_true_if_it_does_not_overlap($scheduleQueryHelper)
  {
      $scheduleQueryHelper-&gt;getSchedulesBetween('slug', $this-&gt;validIntended)-&gt;willReturn([]);
      $this-&gt;doesNotOverlap('slug', $this-&gt;validIntended)-&gt;shouldReturn(true);
  }
  </code></pre>
  
  <p>And back in my ScheduleTimesValidator class did</p>
  
  <pre><code>public function doesNotOverlap($slug, $intended)
  {
      $schedules = $this-&gt;scheduleQueryHelper-&gt;getSchedulesBetween($slug, $intended);
  
      if(empty($schedules)) {
          return true;
      }
  
      return false;
  }
  </code></pre>
  
  <p>And now PhpSpec is mocking that other class ok. However this seems like a very roundabout way to be doing things.</p>