1
votes

I'm starting with PHP Unit and I'm trying to build a Mock for an Eloquent Model which is required as a dependency in the __construct method for the class to test.

This is the constructor for my class I want to test:

namespace App\Repository\Link;

use App\Repository\RepositoryAbstract;
use Illuminate\Database\Eloquent\Model;

class EloquentLink extends RepositoryAbstract implements LinkInterface
{
    protected $link;

    public function __construct(Model $link)
    {
        $this->link = $link;
    }
}

My test class looks like this:

namespace App\Repository\Link;

use Link as ModelLink; //Link is the Eloquent model to pass as constructor for EloquentLink
use Illuminate\Database\Eloquent\Model as Eloquent; //Link extends Eloquent

class EloquentLinkTest extends \PHPUnit_Framework_TestCase
{
    protected $modelMock;
    protected $link;

    public function setUp() {
        $this->modelMock = $this->getMockBuilder('ModelLink')->getMock();
        $this->link = new EloquentLink($this->modelMock);
    }

    public function testCase()
    {
        //comes here
    }
}

I get this error:

1) App\Repository\Link\EloquentLinkTest::testCase Argument 1 passed to App\Repository\Link\EloquentLink::__construct() must be an instance of Illuminate\Database\Eloquent\Model, instance of Mock_ModelLink_ea1343ff given

How can I make the mock extend the Model class?

1

1 Answers

1
votes
use Link as ModelLink;

This scopes the ModelLink name to point to the Link class that exists in the global namespace for the purposes of the containing file (your test case).

$this->modelMock = $this->getMockBuilder('ModelLink')->getMock();

This will go out and create a mock object of the ModelLink class that exists in the global namespace, in the context of another file, namely whichever class file that contains the definition for the getMockBuilder method.

The point here is that the two contexts are completely different. There is this quote we can look to in the manual for guidance:

Note: Importing rules are per file basis, meaning included files will NOT inherit the parent file's importing rules.

Try changing your call to this and see if it works for you:

$this->modelMock = $this->getMockBuilder('Link')->getMock();

It would be different if you had to pass an instance of a ModelLink object created inside of your test case to getMockBuilder, but since it takes a string as a parameter then we can infer that it must be responsible for creating the mock object solely from the class name. With no other information available to it, you can't pass it an aliased class name and expect it to be able to locate a valid class correctly. In this case it just makes a guess and creates a mock of an empty ModelLink object (with zero relation to your original Link object).