Learn how to write and run different types of tests in Laravel
Testing individual components
// tests/Unit/UserTest.php
class UserTest extends TestCase
{
/** @test */
public function it_can_get_full_name()
{
$user = new User([
'first_name' => 'John',
'last_name' => 'Doe'
]);
$this->assertEquals(
'John Doe',
$user->getFullName()
);
}
/** @test */
public function it_can_check_if_is_admin()
{
$user = User::factory()->create([
'role' => 'admin'
]);
$this->assertTrue($user->isAdmin());
}
}
# Run all tests
php artisan test
# Run specific test file
php artisan test tests/Unit/UserTest.php
# Run specific test method
php artisan test --filter=it_can_get_full_name
factory()
for test data
Testing application features
// tests/Feature/PostTest.php
class PostTest extends TestCase
{
use RefreshDatabase;
/** @test */
public function user_can_create_a_post()
{
$user = User::factory()->create();
$response = $this->actingAs($user)
->post('/posts', [
'title' => 'My First Post',
'content' => 'Post content here'
]);
$response->assertRedirect('/posts');
$this->assertDatabaseHas('posts', [
'title' => 'My First Post',
'user_id' => $user->id
]);
}
/** @test */
public function guests_cannot_create_posts()
{
$response = $this->post('/posts', [
'title' => 'My Post',
'content' => 'Content'
]);
$response->assertRedirect('/login');
$this->assertDatabaseMissing('posts', [
'title' => 'My Post'
]);
}
}
Testing database operations
// tests/Unit/Database/PostFactoryTest.php
class PostFactoryTest extends TestCase
{
use RefreshDatabase;
/** @test */
public function it_creates_post_with_valid_data()
{
$post = Post::factory()
->has(Comment::factory()->count(3))
->create([
'status' => 'published'
]);
$this->assertNotNull($post->title);
$this->assertEquals('published', $post->status);
$this->assertCount(3, $post->comments);
}
/** @test */
public function it_seeds_database_correctly()
{
$this->seed(PostSeeder::class);
$this->assertDatabaseCount('posts', 10);
$this->assertDatabaseHas('posts', [
'status' => 'published'
]);
}
}
RefreshDatabase
trait
Testing with mock objects
/** @test */
public function it_sends_welcome_email()
{
Mail::fake();
$user = User::factory()->create();
Mail::assertNothingSent();
$this->post('/welcome', [
'user_id' => $user->id
]);
Mail::assertSent(WelcomeEmail::class, function ($mail) use ($user) {
return $mail->hasTo($user->email);
});
}
/** @test */
public function it_processes_payment()
{
$this->mock(PaymentGateway::class, function ($mock) {
$mock->shouldReceive('charge')
->once()
->with(100, 'token')
->andReturn([
'success' => true,
'transaction_id' => 'tx_123'
]);
});
$response = $this->post('/payments', [
'amount' => 100,
'token' => 'token'
]);
$response->assertSuccessful();
$this->assertDatabaseHas('payments', [
'transaction_id' => 'tx_123',
'status' => 'completed'
]);
}