0

I can't get PHPUnit's Code Coverage tool to mark this else statement as covered even though it must be or the following line could not be covered. Elsewhere in the same class another line that contains only } else { is correctly marked as covered.

enter image description here

    if (is_string($externalId) && $externalId != '') {
        $sitesIds[] = $externalId;
    } else if ($regionName != null && $regionName != '') {
        $sitesIds = $this->sitesService->getSites($regionName);
        if (!is_array($sitesIds) || count($sitesIds) == 0) {
            throw new \Exception(self::NO_MATCHING_REGION, '404');
        }
    } else {
        throw new \Exception(self::BAD_REQUEST.'. Should specify station or region', '400');
    }
3
  • 1
    I know that getting the one line to go green in a test doesn't improve the code, but my OCD compels me to get that last line covered if I can :-) Commented Jan 16, 2017 at 8:52
  • Does moving else { to separate line chang things? Commented Jan 16, 2017 at 9:27
  • @Furgas No. The } is marked as uncovered, while else { is white, meaning it isn't intended to be covered/tested Commented Jan 16, 2017 at 20:38

2 Answers 2

1

Since else doesn't actually do anything (it can be considered just a label) it won't get covered.

Your problem is that you don't have a test where (is_string($externalId) && $externalId != '') is false, ($regionName != null && $regionName != '') is true and (!is_array($sitesIds) || count($sitesIds) == 0) is false. (You might want to be more specific by using not exactly equal to !== instead of not equal to !=: ($externalId !== '') & ($regionName !== null && $regionName !== ''))

If you can get $sitesIds = $this->sitesService->getSites($regionName); to return an array with at least one element, your red line will be covered and turn green.

The red line is telling you that the closing brace } before the else is technically reachable, but you have no tests that cover it.

Sign up to request clarification or add additional context in comments.

1 Comment

That did it. The previous test only went as far as the throw.
0

With slightly modified source:

class A
{
    const NO_MATCHING_REGION = 1;
    const BAD_REQUEST        = 2;

    private $sitesService = ['a' => ['AA'], 'b'=>12];

    public function a($externalId, $regionName)
    {
        $sitesIds = [];
        if (is_string($externalId) && $externalId != '') {
            $sitesIds[] = $externalId;
        } else {
            if ($regionName != null && $regionName != '') {
                $sitesIds = $this->sitesService[$regionName];
                if (!is_array($sitesIds) || count($sitesIds) == 0) {
                    throw new \Exception(self::NO_MATCHING_REGION, '404');
                }
            } else {
                throw new \Exception(self::BAD_REQUEST.'. Should specify station or region', '400');
            }
        }
        return $sitesIds;
    }
}

The test

class ATest extends \PHPUnit_Framework_TestCase
{

    /**
     * @dataProvider data
     */
    public function testOk($id, $reg, $res)
    {
        $a = new A;
        $r = $a->a($id, $reg);
        $this->assertEquals($res, $r);
    }

    public function data()
    {
        return [
            ['a', 1, ['a']],
            [1,'a', ['AA']]
        ];
    }

    /**
     * @dataProvider error
     * @expectedException \Exception
     */
    public function testNotOK($id, $reg)
    {
        $a = new A;
        $a->a($id, $reg);
    }

    public function error()
    {
        return [
            [1,'b'],
            [1,null]
        ];
    }
}

Covers the else line: enter image description here

PHP 5.6.15-1+deb.sury.org~trusty+1

PHPUnit 4.8.21

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.