Tipps zum Testen von Jobs in der Warteschlange in Laravel

Mary-Kate Olsen
Freigeben: 2024-09-19 22:20:33
Original
358 Leute haben es durchsucht

Bei der Arbeit mit Laravel-Anwendungen kommt es häufig vor, dass ein Befehl eine kostspielige Aufgabe ausführen muss. Um eine Blockierung des Hauptprozesses zu vermeiden, können Sie die Aufgabe auf einen Job verlagern, der von einer Warteschlange verarbeitet werden kann.

Lassen Sie uns ein Beispiel durchgehen. Stellen Sie sich vor, der Befehl app:import-users müsste eine große CSV-Datei lesen und für jeden Eintrag einen Benutzer erstellen. So könnte der Befehl aussehen:

/* 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.');
    }
}
Nach dem Login kopieren

In diesem Beispiel sendet der Befehl einen Job, der das Lesen der Datei und das Erstellen von Benutzern übernimmt. So könnte die ImportUsersJob.php aussehen:

/* 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'],
            ]);
        }
    }
}
Nach dem Login kopieren

Beim Testen dieser Funktion könnte ein typischer Test für den Befehl so aussehen:

/* 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);
    }
}
Nach dem Login kopieren

Auf den ersten Blick scheint dieser Test perfekt zu funktionieren. Das Ausführen der Testsuite zeigt ein erfolgreiches Ergebnis:

Tips for testing queued jobs in Laravel

Ausführung in der realen Welt

Wenn Sie jedoch den Befehl app:import-users in einer realen Umgebung ausführen, erhalten Sie möglicherweise ein unerwartetes Ergebnis:

Tips for testing queued jobs in Laravel

Wie Sie sehen können, zeigt die Befehlsausgabe an, dass sich in der Datenbank 0 Benutzer befinden. Also, warum passiert das?

Der Grund dafür ist, dass der Job an eine Warteschlange gesendet wird und daher nicht synchron mit der Befehlsausführung ausgeführt wird. Die Benutzer werden erst erstellt, wenn die Warteschlange den Job später verarbeitet.

Warum besteht der Test?

Die Testsuite verwendet standardmäßig den Synchronisierungswarteschlangentreiber, was bedeutet, dass Aufträge während des Tests synchron verarbeitet werden. Dadurch wird der Job sofort ausgeführt, was den Eindruck vermittelt, dass alles wie erwartet funktioniert.

Während dieses Verhalten in der Testumgebung akzeptabel ist, ist es wichtig zu erkennen, dass reale Ergebnisse von der QUEUE_CONNECTION-Konfiguration in Ihrer Produktionsumgebung abhängen. Und angesichts Ihrer Projektanforderungen wissen Sie möglicherweise, dass der Auftrag in einer asynchronen Warteschlange verarbeitet wird.

Sobald Sie sich dieser Unterscheidung bewusst sind, möchten Sie möglicherweise Ihre Tests verbessern, um „falsch positive Ergebnisse“ zu vermeiden.

Die Prüfung Ihres Auftrags wird versandt

Zunächst ist es wichtig zu überprüfen, ob der Befehl den Job tatsächlich auslöst, unabhängig davon, ob der Job synchron oder asynchron verarbeitet wird. So testen Sie das:

/* 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);
    }
}
Nach dem Login kopieren

Die Prüfung Ihres Jobs wird bearbeitet

Sobald Sie bestätigt haben, dass der Job versandt wurde, können Sie die tatsächliche Arbeit des Jobs in einem separaten Test testen. So könnten Sie den Test für die Stelle strukturieren:

/* 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);
    }
}

Nach dem Login kopieren

Dadurch wird sichergestellt, dass der Job die erforderliche Arbeit ausführt, unabhängig davon, ob er von einer Warteschlange oder synchron verarbeitet wird.

Umgang mit Randfällen

Wie im wirklichen Leben können Randfälle auftreten und Sie sollten darauf vorbereitet sein.

Das Warteschlangensystem von Laravel wird je nach Konfiguration Ihrer Mitarbeiter Aufträge wiederholen, wenn eine Ausnahme auftritt, und wenn die Anzahl der Wiederholungsversuche überschritten wird, wird der Auftrag als fehlgeschlagen markiert.

Was passiert also, wenn die Datei nicht existiert? Sie müssen mit solchen Grenzfällen umgehen, indem Sie Eingaben validieren und bei Bedarf Ausnahmen auslösen.

So könnten Sie in Ihrem Job damit umgehen:

/* 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'],
            ]);
        }
    }
}
Nach dem Login kopieren

So würden Sie dieses Szenario testen:

/* 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());
    }
}

Nach dem Login kopieren

Letzte Gedanken

Dieser Ansatz stellt sicher, dass Ihre Tests genauer widerspiegeln, wie Aufträge in der realen Welt verarbeitet werden.
Die gleiche Strategie kann angewendet werden, wenn ein Controller einen Job an eine Warteschlange sendet oder wenn ein Ereignis-Listener in der Warteschlange steht.
Passen Sie diese Vorgehensweisen wie immer an Ihr Projekt und Ihr Team an.

Ich würde gerne Ihre Meinung hören!

Das obige ist der detaillierte Inhalt vonTipps zum Testen von Jobs in der Warteschlange in Laravel. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Quelle:dev.to
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Neueste Artikel des Autors
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage
Über uns Haftungsausschluss Sitemap
Chinesische PHP-Website:Online-PHP-Schulung für das Gemeinwohl,Helfen Sie PHP-Lernenden, sich schnell weiterzuentwickeln!