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

kmnurunnabi's avatar

Trying to know Best Practices of Laravel unit tests

Hey. In a project, beside feature tests I had some unit tests that was testing of my laravel service class given below:

PostService.php

<?php

namespace App\Services;

use App\Constants\MediaCollectionName;
use App\Models\Post;
use Illuminate\Support\Facades\DB;

class PostService
{
    public function store(array $data, $image = null)
    {
        return DB::transaction(function () use ($data, $image) {
            $post = auth()->user()->posts()->create($data);

            if ($image) {
                $post
                    ->addMedia($image)
                    ->toMediaCollection(MediaCollectionName::POST_IMAGE);
            }

            return $post;
        }, 3);
    }

    public function update(Post $post, array $data, $image = null)
    {
        return DB::transaction(function () use ($post, $data, $image) {
            $post->update($data);

            if ($image) {
                $post
                    ->addMedia($image)
                    ->toMediaCollection(MediaCollectionName::POST_IMAGE);
            }

            return $post;
        }, 3);
    }
}

PostServiceTest.php

<?php

namespace Tests\Unit\Services;

use App\Models\Post;
use App\Services\PostService;
use Illuminate\Http\UploadedFile;
use PHPUnit\Framework\TestCase;
use Illuminate\Support\Facades\DB;

class PostServiceTest extends TestCase
{
    public $postMock;

    public function setUp(): void
    {
        parent::setUp();

        $this->postMock = $this->createMock(Post::class);
    }

    public function test_store_method()
    {
        DB::shouldReceive('transaction')
            ->once()
            ->andReturn($this->postMock);

        $result = resolve(PostService::class)->store([
            'body' => 'A new post',
        ]);

        $this->assertInstanceOf(Post::class, $result);
    }

    public function test_store_method_with_image()
    {
        DB::shouldReceive('transaction')
            ->once()
            ->andReturn($this->postMock);

        $image = UploadedFile::fake()->image('image.png');

        $result = resolve(PostService::class)->store(
            [
                'body' => 'A new post',
            ],
            $image,
        );

        $this->assertInstanceOf(Post::class, $result);
    }

    public function test_store_method_with_incorrect_parameters()
    {
        $this->expectException('TypeError');

        resolve(PostService::class)->store('data');
    }

    public function test_update_method()
    {
        DB::shouldReceive('transaction')
            ->once()
            ->andReturn($this->postMock);

        $result = resolve(PostService::class)->update(
            $this->postMock,
            [
                'body' => 'Updated post',
            ],
        );

        $this->assertInstanceOf(Post::class, $result);
    }

    public function test_update_method_with_image()
    {
        DB::shouldReceive('transaction')
            ->once()
            ->andReturn($this->postMock);

        $image = UploadedFile::fake()->image('image.png');

        $result = resolve(PostService::class)->update(
            $this->postMock,
            [
                'body' => 'Updated post',
            ],
            $image,
        );

        $this->assertInstanceOf(Post::class, $result);
    }

    public function test_update_method_with_incorrect_parameters()
    {
        $this->expectException('TypeError');

        resolve(PostService::class)->update('data');
    }
}

But problem is: someone suggest me your feature tests are ok, but unit tests might be improved and not should be like that. But I have no idea why he said it like that, and which best practices should I follow in order to write good unit test rather than given????

Somebody help me to know the best practices of laravel unit test...

0 likes
0 replies

Please or to participate in this conversation.