Laravel에서 대기 중인 작업을 테스트하기 위한 팁

Mary-Kate Olsen
풀어 주다: 2024-09-19 22:20:33
원래의
430명이 탐색했습니다.

Laravel 애플리케이션으로 작업할 때 명령이 비용이 많이 드는 작업을 수행해야 하는 시나리오를 접하는 것이 일반적입니다. 기본 프로세스를 차단하지 않으려면 대기열에서 처리할 수 있는 작업으로 작업을 오프로드하기로 결정할 수 있습니다.

예제를 살펴보겠습니다. app:import-users 명령이 대용량 CSV 파일을 읽고 각 항목에 대해 사용자를 생성해야 한다고 상상해 보세요. 명령의 모양은 다음과 같습니다.

/* ImportUsersCommand.php */

namespace App\Console\Commands;

/*...*/

class ImportUsersCommand extends Command
{
    protected $signature = 'app:import-users';

    public function handle()
    {
        dispatch(new ImportUsersJob());

        $this->line('Users imported successfully.');
        $this->line('There are: ' . User::count(). ' Users.');
    }
}
로그인 후 복사

이 예에서 명령은 파일 읽기 및 사용자 생성을 처리하는 작업을 전달합니다. ImportUsersJob.php의 모습은 다음과 같습니다.

/* ImportUsersJob.php */

namespace App\Jobs;

/*...*/

class ImportUsersJob implements ShouldQueue
{
    public function handle(FileReader $reader): void
    {   
        foreach($reader->read('users.csv') as $data) {
            User::create([
                'name' => $data['name'], 
                'email' => $data['email'],
            ]);
        }
    }
}
로그인 후 복사

이 기능을 테스트할 때 명령에 대한 일반적인 테스트는 다음과 같습니다.

/* ImportUsersCommandTest.php */

namespace Tests\Feature;

/*...*/

class ImportUsersCommandTest extends TestCase
{
    use RefreshDatabase;

    public function test_it_processes_the_file(): void
    {
        Storage::fake('local')->put('users.csv', "...");

        $this->artisan('app:import-users')
            ->expectsOutput('Users imported successfully.')
            ->expectsOutput('There are: 10 Users.')
            ->assertSuccessful();

        $this->assertDatabaseCount('users', 10);
    }
}
로그인 후 복사

언뜻 보면 이 테스트는 완벽하게 작동하는 것 같습니다. 테스트 스위트를 실행하면 성공적인 결과가 표시됩니다.

Tips for testing queued jobs in Laravel

실제 실행

그러나 실제 환경에서 app:import-users 명령을 실행하면 예상치 못한 결과가 나타날 수 있습니다.

Tips for testing queued jobs in Laravel

보시다시피, 명령 출력은 데이터베이스에 0명의 사용자가 있음을 나타냅니다. 그렇다면 왜 이런 일이 발생하는 걸까요?

이유는 작업이 대기열로 전달되므로 명령 실행과 동기적으로 실행되지 않기 때문입니다. 사용자는 나중에 대기열이 작업을 처리할 때만 생성됩니다.

테스트가 통과되는 이유는 무엇입니까?

테스트 모음은 기본적으로 동기화 대기열 드라이버를 사용합니다. 즉, 테스트 중에 작업이 동기식으로 처리됩니다. 결과적으로 작업이 즉시 실행되어 모든 것이 예상대로 작동한다는 생각을 갖게 됩니다.

이 동작은 테스트 환경에서는 허용되지만 실제 결과는 프로덕션 환경의 QUEUE_CONNECTION 구성에 따라 달라진다는 점을 인식하는 것이 중요합니다. 그리고 프로젝트 요구 사항에 따라 작업이 비동기 대기열에서 처리된다는 것을 알 수 있습니다.

이러한 차이점을 알고 나면 "오탐지"를 방지하기 위해 테스트를 개선할 수 있습니다.

작업 테스트가 발송되었습니다.

먼저 작업이 동기적으로 처리되는지 비동기적으로 처리되는지에 관계없이 명령이 실제로 작업을 전달하는지 확인하는 것이 중요합니다. 이를 테스트하는 방법은 다음과 같습니다.

/* ImportUsersCommandTest.php */

namespace Tests\Feature;

/*...*/

class ImportUsersCommandTest extends TestCase
{    
    public function test_it_dispatches_the_job(): void
    {
        Queue:fake();

        $this->artisan('app:import-users')
            ->expectsOutput('Process has been queued.')
            ->assertSuccessful();

        Queue::assertPushed(ImportUsersJob::class);
    }
}
로그인 후 복사

작업 테스트가 처리되었습니다.

작업이 디스패치된 것을 확인한 후 별도의 테스트를 통해 해당 작업이 수행하는 실제 작업을 테스트할 수 있습니다. 직무에 대한 테스트를 구성하는 방법은 다음과 같습니다.

/* ImportUsersJobTest.php */

namespace Tests\Feature;

/*...*/

class ImportUsersJobTest extends TestCase
{
    use refreshDatabase;

    public function test_it_processes_the_file()
    {
        Storage::fake('local')->put('users.csv', "...");

        app()->call([new ImportUsersJob(), 'handle']);

        $this->assertDatabaseCount('users', 10);
    }
}

로그인 후 복사

이렇게 하면 작업이 대기열에 의해 처리되거나 동기적으로 처리되는지 여부에 관계없이 필요한 작업이 수행됩니다.

극단적인 경우 처리

실생활에서와 마찬가지로 극단적인 경우가 발생할 수 있으므로 이에 대비해야 합니다.

Laravel의 대기열 시스템은 작업자 구성에 따라 예외가 발생하면 작업을 다시 시도하고, 재시도 횟수를 초과하면 작업이 실패한 것으로 표시됩니다.

그럼 파일이 없으면 어떻게 되나요? 입력의 유효성을 검사하고 필요한 경우 예외를 발생시켜 이러한 극단적인 경우를 처리해야 합니다.

직업에서 이 문제를 처리하는 방법은 다음과 같습니다.

/* ImportUsersJobTest.php */

namespace App\Jobs;

/*...*/

class ImportUsersJob implements ShouldQueue
{
    use Queueable;

    public function handle(FileReader $reader): void
    {   
        if(!Storage::disk('local')->exists('users.csv')){
            throw new Exception('The users.csv file doesn\'t exist.')
        }

        foreach($reader->read('users.csv') as $data) {
            User::create([
                'name' => $data['name'], 
                'email' => $data['email'],
            ]);
        }
    }
}
로그인 후 복사

이 시나리오를 테스트하는 방법은 다음과 같습니다.

/* ImportUsersJobTest.php */

namespace Tests\Feature;

/*...*/

class ImportUsersJobTest extends TestCase
{
    use refreshDatabase;

    /*...*/

    public function test_it_fails_when_file_doesnt_exist(): void
    {
        Storage::fake('local');

        $this->expectException(Exception::class);
        $this->expectExceptionMessage('The users.csv file doesn\'t exist.');

        dispatch(new ImportUsersJob());
    }
}

로그인 후 복사

최종 생각

이 접근 방식을 사용하면 테스트가 실제 세계에서 작업이 처리되는 방식을 더 정확하게 반영할 수 있습니다.
컨트롤러가 작업을 대기열에 디스패치하거나 이벤트 리스너가 대기열에 있는 경우에도 동일한 전략을 적용할 수 있습니다.
언제나 그렇듯이 이러한 방식을 프로젝트와 팀에 맞게 조정하세요.

여러분의 생각을 듣고 싶습니다!

위 내용은 Laravel에서 대기 중인 작업을 테스트하기 위한 팁의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

원천:dev.to
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
저자별 최신 기사
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿
회사 소개 부인 성명 Sitemap
PHP 중국어 웹사이트:공공복지 온라인 PHP 교육,PHP 학습자의 빠른 성장을 도와주세요!