sebastianbergmann/phpunit-mock-objects

Fatal error "cannot implement previously implemented interface" with array of single interface

Opened this issue · 4 comments

PHPUnit fails with fatal error "cannot implement previously implemented interface" when mock is generated via TestCase $this->createMock() where the argument is an array containing only one interface. The issue is present in version 4.0.1.

Example error:

Fatal error: Class Mock_SomeInterface_6cf8ec68 cannot implement previously implemented interface My\Test\SomeInterface in vendor\phpunit\phpunit-mock-objects\src\Generator.php(263) : eval()'d code on line 1

Code to reproduce:

<?php

namespace My\Test;

use PHPUnit\Framework\TestCase;

interface SomeInterface
{
}

class ThingTest extends TestCase
{
    public function testThing()
    {
        $mock = $this->createMock([
            SomeInterface::class,
        ]);
    }
}

Works for me with PHPUnit 5.7 and PHPUnit 6.0:

<?php
use PHPUnit\Framework\TestCase;

interface SomeInterface
{
}

class ThingTest extends TestCase
{
    public function testThing()
    {
        $this->createMock([SomeInterface::class]);
    }
}
$ php phpunit-5.7.phar ThingTest     
PHPUnit 5.7.16 by Sebastian Bergmann and contributors.

.                                                                   1 / 1 (100%)

Time: 82 ms, Memory: 10.00MB

OK (1 test, 0 assertions)
$ php phpunit-6.0.phar ThingTest
PHPUnit 6.0.9 by Sebastian Bergmann and contributors.

R                                                                   1 / 1 (100%)

Time: 62 ms, Memory: 8.00MB

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

When I simplified my code for the example I saw it pass once, then I rewrote again. Clearly there's something else going on though. I'll investigate further tomorrow to see whether it's a false alarm or whether my snippet is to blame. Thanks.

Splitting the interface into a separate namespace seems to reproduce the problem, for me and a colleague. Hopefully this works for you too.

ThingTest.php

<?php

require 'FishInterface.php';

use Animal\Fish\FishInterface;
use PHPUnit\Framework\TestCase;

class ThingTest extends TestCase
{
    public function testThing()
    {
        $this->createMock([FishInterface::class]);
    }
}

FishInterface.php

<?php

namespace Animal\Fish;

interface FishInterface
{
}

@KGrey

Works fine for me, too!