php – Testing a User model outside Laravel-ThrowExceptions

Exception or error:

Introduction

I’m running a system with several microservices (9+). Each is separate microservice is an instance of Laravel.

To unify and centralise parts of the codebase, an external private composer repo of shared elements has been created. These include models, interfaces, traits, clients etc. For example, the User object is used across many of the microservices.

This repo is not a Laravel installation, it is simply “some code” and does not require a wrapper/executable element. It follows the standard composer structure (/src/ etc).

I have a piece of code that does some validation. One of the elements requires a User object. This fully works inside the existing codebase.

I am attempting to unit test this code to prove this. This is where the problem begins:


// The class: 

namespace Example\Models\Core;

// ... other usual laravel use statements:
use Illuminate\Foundation\Auth\User as Authenticatable;

class User extends Authenticatable
{

}

Inside the test:


// ... other includes: 
use Example\Models\Core\User;

class ClientTest extends TestCase
{

    public function testUserIssue() 
    {
    // attempt to instantiate an empty user:
    $user = new User();

    // other items:
    }
}

When the unit tests are run, this causes:

Error: Class 'Illuminate\Foundation\Auth\User' not found

The User class extends Illuminate\Foundation\Auth\User. This is inside the vendor folder. It appears to be correctly autoloaded and PhPStorm’s “click through” auto class jumping works as expected.

User objects function as expected when this repo is loaded and used inside a laravel installation. All my other microservices can use the User object as expected

This persists after composer update/install/dump-autoload.

To be clear: I simply want to pass a dumb User object through to a type-hinted function. All that is required is one property ($user->name) inside this function. No DB lookups, or other fancy stuff is required.

Using the following inside the also fails the same:

  • $user = $this->createMock(User::class);
  • $user = $this->createPartialMock(User::class, []);

Question 1

Why is this class unable to be instantiated / how do I instantiate this

Question 2

Is it possible to instantiate a class with ignores dependencies… Essentially a stdClass() or anonymous class that overwrites another object for testing purposes?

How to solve:

Regarding question 1:

I was able to load the class manually with an include(). This was unsatisfactory, but led me toward a more appropriate solution.

Pulling the individual classes/dependancies using composer wasn’t getting them in a way that PSR-4 auto loading seemed to like.

By replacing the individual composer libraries with just "laravel/framework": "^7.0" the internal structure seemed to work.

This couples the code to Laravel, which is not ideal, but given that these are Laravel microservices, this is to be expected. There’s also a lot more code than is actually needed, and this bloats the vendor folder (if only for the common files repo).

Regarding question 2:

There doesn’t seem to be a way.

Leave a Reply

Your email address will not be published. Required fields are marked *