Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PHPUnit Code Coverage & Exceptions

I suspect PHPUnit is showing that 1 line of code is not covered by unit tests because of exceptions thats thrown (but I caught)

I have unit test that should cover that line

/**
 * @expectedException Doctrine\ORM\NoResultException
 */
public function testCannotLoginInvalidUser() {

  $user = User::login($this->em, 'nonExistant', 'password');
  $this->assertNull($user);

}

Why is my code coverage still reflecting that is not covered?

I did a test ... added echo b4 returning null ... I found that that line is really not covered ...

try {
  $user = $query->getSingleResult();
} catch (Exception $e) {
  echo 'caught exception';  <-- this does not get executed. 
  return null;
}

Is PHPUnit skipping all execution once an exception is thrown?

UPDATE: I got a feeling that I am using @expectedException wrong tho ...

like image 250
Jiew Meng Avatar asked Dec 18 '10 07:12

Jiew Meng


2 Answers

Your code samples are just the tip of the iceberg, its hard to pinpoint the exact problem.

But one detail seems suspicious to me: given that your login method is in the Application\Models then, the following code

try {
  $user = $query->getSingleResult();
} catch (Exception $e) {

will not catch any exception, it would catch \Application\Models\Exception - if you even have such a class defined.

Maybe that is the reason why your exception handler does not run.

like image 95
Anti Veeranna Avatar answered Sep 21 '22 06:09

Anti Veeranna


The @expectedException Annotation is similar to this testcode:

public function testDoStuff() {
    try { 
        doStuff();
    } catch(Exception $e) {
        // Test passed
        return;
    }
    $this->fail("Exception not thrown, test failed !");
}

so you can not (should not) test two things at once in that Testcase. (If the exception is thrown AND the return value)

If you want to test that User::login throws an exception you are good to go for that testcase and the assertion isn't needed (that code isn't executed anyways :) )

To get the red line covered you'd need to write code so $query->getSingleResult() throws an exception. That could be tricky but since i don't see enough of the source (like where the query object is coming from) i can't be specific here.

If the $query object is a mock let it throw an exception on ->getSingleResult and write testcase checking for "null"

like image 35
edorian Avatar answered Sep 23 '22 06:09

edorian