title: Using expectException and a spy in PHPUnit
body: <p>I'm using PHPUnit <code>~5.2</code> and PHP <code>~7.0.0</code>.</p>
  
  <p>I have a class that wraps a repository, catches the exceptions it throws, calls a logger and then rethrows the exception.</p>
  
  <pre><code>public function storeDonation( Donation $donation ) {
      try {
          $this-&gt;repository-&gt;storeDonation( $donation );
      }
      catch ( StoreDonationException $ex ) {
          $this-&gt;logger-&gt;log( $this-&gt;logLevel, $ex-&gt;getMessage(), [ 'exception' =&gt; $ex ] );
          throw $ex;
      }
  }
  </code></pre>
  
  <p>In my tests I've created a spy for the logger, so I can see which calls where made to the logging functions. This spy is a dedicated test double NOT created via the PHPUnit mocking API. The issue I'm running into would not occur when using the PHPUnit mocking API, however I'm not asking about feedback for that decision here.</p>
  
  <p>The test method where I'm running into problems has some setup code, then it has a call to PHPUnits <code>expectException</code> (which used to be <code>setExpectedException</code> in PHPUnit 5.1 and older), then calls the production method, and finally gets the logging calls from the spy to assert the right ones where made.</p>
  
  <pre><code>public function testWhenGetDonationByIdThrowException_itIsLoggedAndThrown() {
      $logger = new LoggerSpy();
  
      $loggingRepo = new LoggingDonationRepository(
          $this-&gt;newThrowingRepository(),
          $logger
      );
  
      $this-&gt;expectException( GetDonationException::class );
      $loggingRepo-&gt;getDonationById( 1337 );
  
      $this-&gt;assertEquals(
          [
              [
                  LogLevel::CRITICAL,
                  self::GET_DONATION_BY_ID_EXCEPTION_MESSAGE,
                  $this-&gt;newGetDonationException()
              ]
          ],
          $logger-&gt;getLogCalls()
      );
  }
  </code></pre>
  
  <p>The problem is that when the exception gets thrown, PHPUnit catches it and evaluates <code>expectException</code>, after which execution of my test method does not continue. The assertions using my spy thus never run.</p>
  
  <p>I'm looking for a way to solve this. I've considered splitting the method into one that has the <code>expectException</code> part, and another that has both a dummy try-catch for the production code call and the assertions for the spy. Any suggestions of nicer approaches?</p>