Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cannot double interfaces that declare a constructor with PHP 8 #4139

Closed
MaxSem opened this issue Mar 17, 2020 · 3 comments
Closed

Cannot double interfaces that declare a constructor with PHP 8 #4139

MaxSem opened this issue Mar 17, 2020 · 3 comments
Assignees
Labels
feature/test-doubles Test Stubs and Mock Objects type/bug Something is broken

Comments

@MaxSem
Copy link

MaxSem commented Mar 17, 2020

Q A
PHPUnit version 9.0.1
PHP version 8.0.0-dev
Installation Method Composer

Summary

$ cat test.php
<?php

interface ITest {
        function __construct();
}

class Test extends PHPUnit\Framework\TestCase {
                public function testMock() {
                                $mock = $this->createMock(ITest::class);
                }

                public function testMockBuilder() {
                                $mock = $this->getMockBuilder(ITest::class)->getMock();
                }
}

$ php --version
PHP 8.0.0-dev (cli) (built: Mar 17 2020 16:36:19) ( NTS )
Copyright (c) The PHP Group
Zend Engine v4.0.0-dev, Copyright (c) Zend Technologies

$ php vendor/bin/phpunit test.php
PHPUnit 9.0.1 by Sebastian Bergmann and contributors.


Fatal error: Class Mock_ITest_d9ac1e16 contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (ITest::__construct) in .../vendor/phpunit/phpunit/src/Framework/MockObject/MockClass.php(42) : eval()'d code on line 3

Expected behavior

For example, older PHPUnit on PHP 7.2:

PHPUnit 8.5.2 by Sebastian Bergmann and contributors.

RR                                                                  2 / 2 (100%)

Time: 187 ms, Memory: 6.00 MB

There were 2 risky tests:

1) Test::testMock
This test did not perform any assertions

.../test.php:8

2) Test::testMockBuilder
This test did not perform any assertions

.../test.php:12

OK, but incomplete, skipped, or risky tests!
Tests: 2, Assertions: 0, Risky: 2.

An example of such interface in the wild

I know PHP 8 is still in the early stages of development, however PHPUnit claims to support it, so I'd rather make this issue known.

@MaxSem MaxSem added the type/bug Something is broken label Mar 17, 2020
@sebastianbergmann
Copy link
Owner

While PHPUnit is tested on PHP 8 in continuous integration, PHPUnit is not supported on PHP 8 yet.

@sebastianbergmann sebastianbergmann added the feature/test-doubles Test Stubs and Mock Objects label Mar 18, 2020
@sebastianbergmann sebastianbergmann self-assigned this Mar 28, 2020
@sebastianbergmann
Copy link
Owner

sebastianbergmann commented Mar 28, 2020

Code generated with PHP 7.4

class Mock_I_abd6e555 implements PHPUnit\Framework\MockObject\MockObject, I
{
    use \PHPUnit\Framework\MockObject\Api;
    use \PHPUnit\Framework\MockObject\Method;
    use \PHPUnit\Framework\MockObject\MockedCloneMethod;

    public function __construct()
    {
        $__phpunit_arguments = [];
        $__phpunit_count     = func_num_args();

        if ($__phpunit_count > 0) {
            $__phpunit_arguments_tmp = func_get_args();

            for ($__phpunit_i = 0; $__phpunit_i < $__phpunit_count; $__phpunit_i++) {
                $__phpunit_arguments[] = $__phpunit_arguments_tmp[$__phpunit_i];
            }
        }

        $__phpunit_result = $this->__phpunit_getInvocationHandler()->invoke(
            new \PHPUnit\Framework\MockObject\Invocation(
                'I', '__construct', $__phpunit_arguments, '', $this, false
            )
        );

        return $__phpunit_result;
    }
}

Code generated with PHP 8.0

class Mock_I_1b966968 implements PHPUnit\Framework\MockObject\MockObject, I
{
    use \PHPUnit\Framework\MockObject\Api;
    use \PHPUnit\Framework\MockObject\Method;
    use \PHPUnit\Framework\MockObject\MockedCloneMethod;
}

TL;DR: The constructor is missing in the code generated with PHP 8.

@sebastianbergmann sebastianbergmann changed the title Can't mock interfaces with constructor on PHP 8 Cannot double interfaces that declare a constructor with PHP 8 Mar 28, 2020
@sebastianbergmann
Copy link
Owner

The root cause for this is that ReflectionMethod::isConstructor() behaves differently in PHP 7 and PHP 8.

Details can be found here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature/test-doubles Test Stubs and Mock Objects type/bug Something is broken
Projects
None yet
Development

No branches or pull requests

2 participants