userRepo = new FakeUserRepository(); $this->hasher = new FakePasswordHasher(); $this->useCase = new AuthenticateUser( $this->userRepo, $this->hasher, ); $this->userRepo->create(new CreateUserDto( email: new EmailAddress('user@example.com'), passwordHash: $this->hasher->hash('correct-password'), )); } public function testAuthenticatesWithValidCredentials(): void { $user = $this->useCase->execute(new AuthenticateUserRequest( email: 'user@example.com', password: 'correct-password', )); $this->assertSame('user@example.com', $user->getEmail()->value()); } public function testThrowsBadRequestWhenEmailIsEmpty(): void { $this->expectException(BadRequestException::class); $this->expectExceptionMessage('email is required'); $this->useCase->execute(new AuthenticateUserRequest( email: '', password: 'some-password', )); } public function testThrowsBadRequestWhenPasswordIsEmpty(): void { $this->expectException(BadRequestException::class); $this->expectExceptionMessage('password is required'); $this->useCase->execute(new AuthenticateUserRequest( email: 'user@example.com', password: '', )); } public function testThrowsBadRequestWhenEmailIsNull(): void { $this->expectException(BadRequestException::class); $this->expectExceptionMessage('email is required'); $this->useCase->execute(new AuthenticateUserRequest( email: null, password: 'some-password', )); } public function testThrowsBadRequestWhenPasswordIsNull(): void { $this->expectException(BadRequestException::class); $this->expectExceptionMessage('password is required'); $this->useCase->execute(new AuthenticateUserRequest( email: 'user@example.com', password: null, )); } public function testThrowsUnauthorizedForUnknownEmail(): void { $this->expectException(UnauthorizedException::class); $this->expectExceptionMessage('invalid credentials'); $this->useCase->execute(new AuthenticateUserRequest( email: 'unknown@example.com', password: 'some-password', )); } public function testThrowsUnauthorizedForWrongPassword(): void { $this->expectException(UnauthorizedException::class); $this->expectExceptionMessage('invalid credentials'); $this->useCase->execute(new AuthenticateUserRequest( email: 'user@example.com', password: 'wrong-password', )); } public function testReturnsNewInstanceOnEachCall(): void { $user1 = $this->useCase->execute(new AuthenticateUserRequest( email: 'user@example.com', password: 'correct-password', )); $user2 = $this->useCase->execute(new AuthenticateUserRequest( email: 'user@example.com', password: 'correct-password', )); $this->assertNotSame($user1, $user2); } }