Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

Pxscal's avatar
Level 1

Laravel Unit testing approach

Hi everyone,

I'm currently trying to write unit tests for my AuthController in Laravel. However, I'm unsure whether my approach qualifies as a unit test or if it's more of a feature test

Here is my AuthController I´m working with:

public function login(Request $request) { $validator = Validator::make($request->only('username', 'password'), [ 'username' => 'required|string|max:255', 'password' => 'required|string|min:8', ]);

if ($validator->fails()) {
    return response()->json(['message' => 'Validation failed'], 422);
}

if (Auth::attempt(['username' => $request->username, 'password' => $request->password])) {
    $user = Auth::user();
    $token = $user->createToken('UserAuth')->plainTextToken;
    return response()->json(['user' => $user, 'token' => $token], 200);
}

return response()->json(['message' => 'Invalid credentials'], 401);

}

There are a few unit tests i wrote

lass AuthControllerTest extends TestCase { /** * A basic unit test example. */ use RefreshDatabase; #[\PHPUnit\Framework\Attributes\Test] public function Test_true_credentials_login_(): void { $role = Role::create(['role_name' => 'Patient']);

   $user = User::create([
    'username' => 'Pxscal',
    'password' => 'Blubberbernd123',
    'role_id' => $role->role_id,
   ]);
   $response = $this->call('POST','/api/login',[
    'username' => 'Pxscal',
    'password'=> 'Blubberbernd123',
   ]);
   $response->assertStatus(200);


}
#[\PHPUnit\Framework\Attributes\Test]
public function Test_false_password_login_(): void
{
   $role = Role::create(['role_name' => 'Patient']);

   $user = User::create([
    'username' => 'Pxscal',
    'password' => 'Blubberbernd1234',
    'role_id' => $role->role_id,
   ]);
   $response = $this->call('POST','/api/login',[
    'username' => 'Pxscal',
    'password'=> 'Blubberbernd123',
   ]);
   $response->assertStatus(401);


}

Thanks for help!

0 likes
7 replies
tykus's avatar

It is objectively not a Unit Test; you are testing more than a unit of code here - you create instances of Role, User, and use the database, TestResponse and Request classes. If you want a simple heuristic to determine if it is a Unit or Feature test; try extending PHPUnit\Framework\TestCase rather than Tests\TestCase class - if it needs the framework booted, then it is not a unit test.

Did you have a concern beyond classifying the tests?

1 like
Pxscal's avatar
Level 1

@tykus Thank you for reply.

Is There any approach to do unit tests? My main concern is writing Unit Tests for my semester project. Most of my controller logic depends on models and request data, I´m not sure how to test this without it feeling like a Feature Test.

Pxscal's avatar
Level 1

Would be mocking such as the models an suitable approach?

tykus's avatar

@Pxscal if you are testing the full request/response cycle, then it will never be considered a Unit Test IMHO; in the context of a Controller action (and associated middleware, validation, side-effects), the Request/Response is all we really care about. Most of my code for a Laravel application will be feature tests like this; with Unit Tests being reserved for discrete units of code

1 like
Pxscal's avatar
Level 1

@tykus I get your point that testing the full request/response cycle is considered a feature test but is there no way even with mocking all dependencies? I´m trying hard to understand the distinction between unit tests and feature (integration?) test, especially in Laravel. Also, is an integration test essentially the same as a feature test?"

Thanks for reply

tykus's avatar

@Pxscal

is there no way even with mocking all dependencies

Yes, you can go crazy mocking every last dependency; but IMHO your test becomes very brittle, because you are mirroring implementation details rather than satisfying yourself that your big idea™ actually works!

There are evangelists for unit testing every little thing, but at the end of the day I want to have confidence that the code I have written will do the things the client wants/expects (whenever I send this, I expect that back), and in the main that can be satisfied with Feature tests.

1 like
martinbean's avatar
Level 80

@Pxscal My rule of thumb is: a unit test tests a single method. You pass arguments and you assert the return result. If you need to mock any of the passed arguments, you can. But your test should not rely on anything else outside of that unit of code (the method).

If you need the framework or a database in a test, then it’s not a unit test and is an integration/feature test.

1 like

Please or to participate in this conversation.