0

Preconditions (*)

  1. Magento 2.3.1 upgraded from Magento 2.3.0
  2. Php 7.2.15
  3. OS : Ubuntu 18.04 Bionic
  4. Phpstorm 2019.1.1
  5. Evnironemnt : Magento development
  6. PHPUnit 6.5.0
  7. magento/magento2-functional-testing-framework": "~2.3.13"

Steps to reproduce (*)

  • Follow the code to reproduce the error

Error

PHP Fatal error: Class Mock_LoggerInterface_a49cf619 contains 8 abstract >methods and must therefore be declared abstract or implement the remaining >methods (Psr\Log\LoggerInterface::emergency, Psr\Log>\LoggerInterface::alert, Psr\Log\LoggerInterface::critical, ...) in /var/www/html/myproject/vendor/phpunit/phpunit-mock-objects>/src/Generator.php(264) : eval()'d code on line 1

My class code is given below

use Psr\Log\LoggerInterface;

class Foo {


    private $logger;
    private $myclassObject;

    public function __construct(LoggerInterface $logger)
    {
        $this->logger = $logger;
    }
    public function Bar ()
    {
      // some code
      $logger->debug ('debug message')

    }
}

My Test Class Code is

use PHPUnit\Framework\TestCase;

class FooTest extends TestCase
{

    private $logger;
    public function setUp()
    {
        $this->logger = $this->getMockBuilder('\Psr\Log\LoggerInterface')
            ->setMethods(null)
            ->getMock();

        $this->logger->expects($this->any())
            ->method('debug')
            ->willReturn('Message Logged');
    }

    $this->myclassObject = $this->getMockBuilder('MyVendor\MyModule\Model\Foo')
    ->setMethods(['__construct'])        
    ->setConstructorArgs(['$logger'])
    ->disableOriginalConstructor()
    ->getMock();

    public function testBar()
    {

        $this->assertEquals($expected_result,$this->myclassObject->Bar());
    }
}

I'm expecting a successful unit test.

1 Answer 1

2

You get this error because you are trying to create a mock for an interface via mock builder which should be used to create mocks for classes. There are multiple ways how to create a mock for the interface:

use Psr\Log\LoggerInterface;
//...
$this->logger = $this->getMockForAbstractClass(LoggerInterface::class)

or mock all interface's methods:

$this->logger = $this->getMockBuilder(LoggerInterface::class)
    ->setMethods([
        'emergency',
        'alert',
        'critical',
        'error',
        'warning',
        'notice',
        'info',
        'debug',
        'log'
    ])
    ->getMock();

Also, it's better to use namespace instead of string representation and avoid the usage of FQCN.

Calling expects($this->any()) doesn't make any sense as it will be called by default.

1
  • How can I configure ONLY SOME methods of an abstract and ALSO have all the remaining methods automatically mocked, but WITHOUT having to list them explicitly? Aug 6, 2021 at 15:00

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.