Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PhpUnit when I use Mock Builder for Interface I get the correct class

I have the following class

namespace MyApp;

use MyApp\SomeInterface;

class MyClass
{
  public function __construct(SomeInterface $s)
  {
    //Some Logic here
  }

  //Another methods implemented There
}

The SomeInterface contains the following:

namespace MyApp

interface SomeInterface
{
  /**
  * @return SomeObject
  */
  public function someMethodToImpement();
}

And I want to create a mock over my phpunit Test Class:

namespace Tests\MyApp;

use PHPUnit\Framework\TestCase;
use MyApp\MyClass;
use MyApp\SomeInterface;

class MyClassTest extends TestCase
{
   public function someTest()
   {

     $fakeClass=new class{
          public function myFunction($arg1,$arg2)
          {
            //Dummy logic to test if called
            return $arg1+$arg2;
          }
     };

     $mockInterface=$this->createMock(SomeInterface::class)
      ->method('someMethodToImpement')
      ->will($this->returnValue($fakeClass));

     $myActualObject=new MyClass($mockInterface);
   }
}

But Once I run it I get the error:

Tests\MyApp\MyClassTest::someTest TypeError: Argument 1 passed to MyApp\MyClass::__construct() must implement interface MyApp\SomeInterface, instance of PHPUnit\Framework\MockObject\Builder\InvocationMocker given, called in /home/vagrant/code/tests/MyApp/MyClassTest.php on line

Do you know why that happens and how actually will create the mock Interface?

like image 863
Dimitrios Desyllas Avatar asked Oct 06 '18 11:10

Dimitrios Desyllas


2 Answers

Instead of constructing the mock via

 $mockInterface=$this->createMock(SomeInterface::class)
      ->method('someMethodToImpement')->will($this->returnValue($fakeClass));

Split it into seperate lines:

 $mockInterface=$this->createMock(SomeInterface::class);
 $mockInterface->method('someMethodToImpement')->will($this->returnValue($fakeClass));

And will work like a charm.

like image 55
Dimitrios Desyllas Avatar answered Oct 08 '22 14:10

Dimitrios Desyllas


I've had a similar issue. I fixed it by adding those interfaces as another mock() parameter

class Product implements PriceInterface, ProductDataInterface {
    // ...
}

Test:

// throws error
$product = Mockery::mock(Product::class);
// works fine
$product = Mockery::mock(Product::class, 'PriceInterface, ProductDataInterface');

Link to documentation

like image 33
WellBloud Avatar answered Oct 08 '22 15:10

WellBloud