Erstellen einer Laravel-REST-API mit testgetriebener Entwicklung

Es gibt ein berühmtes Zitat von James Grenning, einem der Pioniere der TDD- und Agile-Entwicklungsmethoden:

Wenn Sie keine testgetriebene Entwicklung durchführen, führen Sie eine spätere Debug-Entwicklung durch - James Grenning

Heute machen wir eine Laravel-Reise, die von Tests angetrieben wird. Wir erstellen eine Laravel-REST-API mit Authentifizierungs- und CRUD-Funktionen, ohne Postman oder einen Browser zu öffnen. ?

Hinweis: In dieser exemplarischen Vorgehensweise wird davon ausgegangen, dass Sie die Grundkonzepte von Laravel und PHPUnit verstehen. Wenn Sie das aus dem Weg haben? Fahren wir los.

Projekt einrichten

Erstellen Sie zunächst ein neues Laravel-Projekt mit composer create-project --prefer-dist laravel/laravel tdd-journey.

Als nächstes müssen wir den Authentifizierungsgerüst ausführen, den wir verwenden würden, und php artisan make:authdann fortfahren php artisan migrate.

Wir werden die generierten Routen und Ansichten nicht verwenden. Für dieses Projekt würden wir jwt-auth verwenden. Richten Sie es also in Ihrer Anwendung ein.

Hinweis: Wenn Sie Fehler mit dem generateBefehl von JWT haben , können Sie diesen Fix befolgen, bis er zur stabilen Version hinzugefügt wurde.

Schließlich können Sie Löschen ExampleTestin beiden den tests/Unitund tests/FeatureOrdner , so dass es nicht mit unseren Testergebnissen nicht stört und wir sind gut zu gehen.

Den Code schreiben

  1. Stellen Sie zunächst Ihre authKonfiguration so ein, dass der JWT-Treiber standardmäßig verwendet wird:

Fügen Sie dann Folgendes zu Ihrer routes/api.phpDatei hinzu:

2. Nachdem wir unseren Treiber eingerichtet haben, richten Sie Ihr Benutzermodell auf die gleiche Weise ein:

Was wir getan haben, war, dass wir nur JWTSubjectdie erforderlichen Methoden implementiert und hinzugefügt haben.

3. Als nächstes müssen wir unsere Authentifizierungsmethoden im Controller hinzufügen.

Führen php artisan make:controller AuthControllerSie die folgenden Methoden aus und fügen Sie sie hinzu:

Dieser Schritt ist ziemlich geradlinig, alles , was wir tun , ist das hinzufügen authenticateund registerMethoden zu unserem Controller. In der authenticateMethode validieren wir die Eingabe, versuchen eine Anmeldung und geben das Token zurück, wenn dies erfolgreich ist. Bei der Registermethode validieren wir die Eingabe, erstellen mit der Eingabe einen neuen Benutzer und generieren darauf basierend ein Token für den Benutzer.

4. Weiter zum guten Teil. Testen, was wir gerade geschrieben haben. Generieren Sie die Testklassen mit php artisan make:test AuthTest. Fügen Sie im neuen tests/Feature/AuthTestdie folgenden Methoden hinzu:

Die Kommentare im obigen Code beschreiben den Code ziemlich genau. Eine Sache, die Sie beachten sollten, ist, wie wir den Benutzer in jedem Test erstellen und löschen. Der springende Punkt bei Tests ist, dass sie im Idealfall unabhängig voneinander und vom Datenbankstatus sein sollten.

Führen Sie es jetzt aus $vendor/bin/phpunitoder $ phpunitwenn Sie es global installiert haben. Wenn Sie dies ausführen, sollten Sie erfolgreiche Aussagen treffen. Wenn dies nicht der Fall war, können Sie die Protokolle durchsuchen, korrigieren und erneut testen. Dies ist der schöne Zyklus von TDD.

5. Nachdem unsere Authentifizierung funktioniert hat, fügen wir das Element für die CRUD hinzu. In diesem Tutorial werden wir Lebensmittelrezepte als CRUD-Elemente verwenden, denn warum nicht?

Beginnen Sie mit der Erstellung unserer Migration php artisan make:migration create_recipes_tableund fügen Sie Folgendes hinzu:

Führen Sie dann die Migration aus. Fügen Sie nun das Modell mit hinzu php artisan make:model Recipeund fügen Sie es unserem Modell hinzu.

Fügen Sie diese Methode dann dem userModell hinzu.

6. Jetzt benötigen wir Endpunkte für die Verwaltung unserer Rezepte. Zuerst erstellen wir den Controller php artisan make:controller RecipeController. Bearbeiten Sie als Nächstes die routes/api.phpDatei und fügen Sie den createEndpunkt hinzu.

Fügen Sie im Controller auch die Methode create hinzu

Generieren Sie den Funktionstest mit php artisan make:test RecipeTestund bearbeiten Sie den Inhalt wie folgt:

Der Code ist selbsterklärend. Wir erstellen lediglich eine Methode, die die Registrierung eines Benutzers und die Token-Generierung übernimmt. Anschließend verwenden wir dieses Token in der testCreate()Methode. Beachten Sie die Verwendung des RefreshDatabaseMerkmals. Das Merkmal ist Laravels bequeme Möglichkeit, Ihre Datenbank nach jedem Test zurückzusetzen. Dies ist perfekt für unser kleines Projekt.

OK, im Moment möchten wir nur den Status der Antwort bestätigen. Fahren Sie fort $ vendor/bin/phpunit.

Wenn alles gut geht, sollten Sie eine Fehlermeldung erhalten. ?

There was 1 failure:
1) Tests\Feature\RecipeTest::testCreateExpected status code 200 but received 500.Failed asserting that false is true.
/home/user/sites/tdd-journey/vendor/laravel/framework/src/Illuminate/Foundation/Testing/TestResponse.php:133/home/user/sites/tdd-journey/tests/Feature/RecipeTest.php:49
FAILURES!Tests: 3, Assertions: 5, Failures: 1.

Mit Blick auf den Log - Dateien, können wir die Täter sehen sind publisherund recipesBeziehung in den Recipeund UserKlassen. Laravel versucht, eine user_idSpalte in der Tabelle zu finden und diese als Fremdschlüssel zu verwenden, aber in unserer Migration legen wir sie publisher_idals Fremdschlüssel fest. Passen Sie nun die Linien wie folgt an:

//Recipe filepublic function publisher(){ return $this->belongsTo(User::class,'publisher_id');}
//User filepublic function recipes(){ return $this->hasMany(Recipe::class,'publisher_id');}

Führen Sie den Test erneut aus. Wenn alles gut geht, bekommen wir alle grünen Tests! ?

... 3 / 3 (100%)
...
OK (3 tests, 5 assertions)

Jetzt müssen wir noch die Erstellung des Rezepts testen. Dazu können wir die Anzahl der Rezepte des Benutzers bestätigen. Aktualisieren Sie Ihre testCreateMethode wie folgt:

Wir können jetzt fortfahren und den Rest unserer Methoden ausfüllen. Zeit für einige Änderungen. Erstens unsereroutes/api.php

Als nächstes fügen wir die Methoden zum Controller hinzu. Aktualisieren Sie Ihre RecipeControllerKlasse auf diese Weise.

Der Code und die Kommentare erklären die Logik bereits zu einem guten Teil.

Zuletzt unsere test/Feature/RecipeTest

Abgesehen vom zusätzlichen Test bestand der einzige andere Unterschied darin, eine klassenweite Benutzerdatei hinzuzufügen. Auf diese Weise authenticategeneriert die Methode nicht nur ein Token, sondern legt die Benutzerdatei für nachfolgende Vorgänge fest.

Führen $ vendor/bin/phpunitSie nun aus und Sie sollten alle grünen Tests durchführen lassen, wenn dies korrekt durchgeführt wurde.

Fazit

Hoffentlich gab Ihnen dies einen Einblick in die Funktionsweise von TDD in Laravel. Es ist definitiv ein viel umfassenderes Konzept als dieses, das nicht an eine bestimmte Methode gebunden ist.

Obwohl diese Entwicklungsmethode später länger als das übliche Debugging erscheinen magVerfahren, es ist perfekt, um Fehler frühzeitig in Ihrem Code zu erkennen. Obwohl es Fälle gibt, in denen ein Nicht-TDD-Ansatz nützlicher ist, ist es immer noch eine solide Fähigkeit und Gewohnheit, sich daran zu gewöhnen.

Der gesamte Code für diese exemplarische Vorgehensweise ist hier auf Github verfügbar. Fühlen Sie sich frei, damit herumzuspielen.

Prost!