Phpunit: Test expecting an exception with method using yield keyword doesn鈥檛 seem to work

Created on 17 Feb 2020  路  2Comments  路  Source: sebastianbergmann/phpunit

| Q | A
| --------------------| ---------------
| PHPUnit version | 9.0-dev
| PHP version | 7.4.2
| Installation Method | PHAR

Summary

If a test is expecting an exception and the tested method contains the yield keyword, the assertion does not work.

How to reproduce

Using the following class:

<?php

final class SomeClass
{
    public static function getSomeStuff(): iterable
    {
        throw new RuntimeException('Some error');

        foreach (['One', 'Two', 'Three'] as $value) {
            yield $value;
        }
    }
}

And the following test:

<?php

use PHPUnit\Framework\TestCase;

final class SomeClassTest extends TestCase
{
    public function testExceptionIsThrown(): void
    {
        $this->expectException(RuntimeException::class);

        SomeClass::getSomeStuff();
    }
}

Current behavior

PHPUnit 9.0-dev by Sebastian Bergmann and contributors.

F                                                                   1 / 1 (100%)

Time: 120 ms, Memory: 10.00 MB

There was 1 failure:

1) SomeClassTest::testExceptionIsThrown
Failed asserting that exception of type "RuntimeException" is thrown.

FAILURES!
Tests: 1, Assertions: 1, Failures: 1.

Expected behavior

PHPUnit 9.0-dev by Sebastian Bergmann and contributors.

.                                                                   1 / 1 (100%)

Time: 91 ms, Memory: 10.00 MB

OK (1 test, 1 assertion)

Thanks a lot for your help!

typbug

All 2 comments

A generator function does not execute immediately when you call it, it returns a Generator object. In order to actually execute your code, you need to start consuming the generator by e.g looping over it.

Here it's an example of how to trigger your exception:

<?php

use PHPUnit\Framework\TestCase;

final class SomeClass
{
    public static function getSomeStuff(): iterable
    {
        throw new RuntimeException('Some error');

        foreach (['One', 'Two', 'Three'] as $value) {
            yield $value;
        }
    }
}

final class SomeClassTest extends TestCase
{
    public function testExceptionIsThrown(): void
    {
        $this->expectException(RuntimeException::class);
        $this->expectExceptionMessage('Some error');

        $generator = SomeClass::getSomeStuff();

        $this->assertInstanceOf(Generator::class, $generator);
        $generator->next();
    }
}

PHPUnit output:

PHPUnit 9.5-g977a70658 by Sebastian Bergmann and contributors.

Runtime:       PHP 7.4.3
Configuration: /workspace/phpunit/phpunit.xml

.                                                                   1 / 1 (100%)

Time: 00:00.004, Memory: 6.00 MB

OK (1 test, 3 assertions)

Oh yeah, does make sense. I changed my code as suggested and it works now, thank you @michaelpaul

Was this page helpful?
0 / 5 - 0 ratings

Related issues

keradus picture keradus  路  4Comments

sebastianbergmann picture sebastianbergmann  路  3Comments

kunjalpopat picture kunjalpopat  路  4Comments

stephen-leavitt-sonyatv-com picture stephen-leavitt-sonyatv-com  路  4Comments

stof picture stof  路  3Comments