1

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 Answer 1

1
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).

Sign up to request clarification or add additional context in comments.

2 Comments

Thank you, I changed one more thing with your information. In the model Link extended Eloquent (which is a laravel alias for Illuminate\Database\Eloquent\Model.) So I changed it to this: class Link extends Illuminate\Database\Eloquent\Model
There's nothing wrong with that, but that 'alias' is provided at a higher level than the PHP language, specifically by the Laravel application. If that was also causing you an issue, then you could probably change your test case to extend from app/tests/TestCase.php rather than directly from PHPUnit_Framework_TestCase. That class will handle bootstrapping the Laravel application (including the Eloquent facade)

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.