Sådan opbygges en Laravel REST API med testdrevet udvikling

Der er et berømt citat af James Grenning, en af ​​pionererne inden for TDD og Agile udviklingsmetoder:

Hvis du ikke laver testdrevet udvikling, laver du debug-senere udvikling - James Grenning

I dag skal vi på en Laravel-rejse drevet af tests. Vi opretter en Laravel REST API komplet med godkendelse og CRUD-funktionalitet uden at åbne Postman eller en browser. ?

Bemærk: Denne gennemgang forudsætter, at du forstår de grundlæggende begreber i Laravel og PHPUnit. Hvis du har det ude af vejen? Lad os køre.

Opsætning af projektet

Start med at oprette et nyt Laravel-projekt med composer create-project --prefer-dist laravel/laravel tdd-journey.

Dernæst er vi nødt til at køre den godkendelsesstillads, som vi bruger, gå videre og kør php artisan make:authderefter php artisan migrate.

Vi bruger faktisk ikke de genererede ruter og visninger. Til dette projekt bruger vi jwt-auth. Så gå videre og sæt det op i din ansøgning.

Bemærk: Hvis du har fejl med JWTs generatekommando, kan du følge denne rettelse, indtil den er blevet føjet til den stabile udgivelse.

Endelig kan du slette ExampleTestbåde i tests/Unitog tests/Featuremapper, så det ikke forstyrrer vores testresultater, og vi er klar til at gå.

Skrivning af koden

  1. Begynd med at indstille din authkonfiguration til at bruge JWT-driveren som standard:

Tilføj derefter følgende til din routes/api.phpfil:

2. Nu hvor vores driver er konfigureret, skal du konfigurere din brugermodel på samme måde:

Hvad vi gjorde var, at vi bare implementerede JWTSubjectog tilføjede de nødvendige metoder.

3. Dernæst skal vi tilføje vores godkendelsesmetoder i controlleren.

Kør php artisan make:controller AuthControllerog tilføj følgende metoder:

Dette trin er ret ligetil, alt hvad vi gør er at tilføje authenticateog registermetoderne til vores controller. I authenticatemetoden validerer vi input, prøver et login og returnerer tokenet, hvis det lykkes. I registermetoden validerer vi input, opretter en ny bruger med input og genererer et token til brugeren baseret på det.

4. Dernæst på den gode del. Tester hvad vi lige har skrevet. Generer testklasser ved hjælp af php artisan make:test AuthTest. I det nye tests/Feature/AuthTesttilføj disse metoder:

Kommentarerne i koden ovenfor beskriver stort set koden. En ting, du skal bemærke, er, hvordan vi opretter og sletter brugeren i hver test. Hele pointen med test er, at de skal være uafhængige af hinanden og databasestatus ideelt.

Kør nu, $vendor/bin/phpuniteller $ phpunithvis du har det globalt installeret. At køre det skal give dig vellykkede påstande. Hvis det ikke var tilfældet, kan du se igennem logfilerne, rette og teste igen. Dette er den smukke cyklus af TDD.

5. Nu hvor vores godkendelse fungerer, lad os tilføje elementet til CRUD. Til denne vejledning skal vi bruge madopskrifter som vores CRUD-emner, fordi hvorfor ikke?

Start med at oprette vores migration php artisan make:migration create_recipes_tableog tilføj følgende:

Kør derefter migrationen. Tilføj nu modellen ved hjælp af php artisan make:model Recipeog tilføj denne til vores model.

Føj derefter denne metode til usermodellen.

6. Nu har vi brug for slutpunkter til styring af vores opskrifter. Først opretter vi controlleren php artisan make:controller RecipeController. Rediger derefter routes/api.phpfilen og tilføj createslutpunktet.

Tilføj også oprettelsesmetoden i controlleren

Generer funktionstesten med php artisan make:test RecipeTestog rediger indholdet som under:

Koden er ret selvforklarende. Alt hvad vi gør er at oprette en metode, der håndterer registreringen af ​​en bruger- og tokengenerering, så bruger vi dette token i testCreate()metoden. Bemærk brugen af RefreshDatabasetræk, træk er Laravels bekvemme måde at nulstille din database på efter hver test, hvilket er perfekt til vores smarte lille projekt.

OK, så for nu er alt, hvad vi vil hævde, status for svaret, gå videre og løb $ vendor/bin/phpunit.

Hvis alt går godt, skal du modtage en fejl. ?

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.

Når man ser på logfilerne, kan vi se, at synderen er publisherog recipesforholdet i Recipeog Userklasser. Laravel forsøger at finde en user_idkolonne i tabellen og bruge den som den fremmede nøgle, men i vores migration angiver vi publisher_idsom den fremmede nøgle. Juster nu linjerne som under:

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

Og kør derefter testen igen. Hvis alt går godt, får vi alle grønne tests! ?

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

Nu skal vi stadig teste oprettelsen af ​​opskriften. For at gøre det kan vi hævde, at brugerens opskrifter tæller. Opdater din testCreatemetode som under:

Vi kan nu gå videre og udfylde resten af ​​vores metoder. Tid til nogle ændringer. Først voresroutes/api.php

Dernæst tilføjer vi metoderne til controlleren. Opdater din RecipeControllerklasse på denne måde.

Koden og kommentarerne forklarer allerede logikken i god grad.

Lastly our test/Feature/RecipeTest

Other than the additional test, the only other difference was adding a class-wide user file. That way, the authenticate method not only generates a token, but it sets the user file for subsequent operations.

Now run $ vendor/bin/phpunit and you should have all green tests if done correctly.

Conclusion

Hopefully, this gave you an insight into how TDD works in Laravel. It is definitely a much wider concept than this, one that is not bound to a specific method.

Though this method of development may seem longer than the usual debug laterprocedure, it’s perfect for catching errors early on in your code. Though there are cases where a non-TDD approach is more useful, it’s still a solid skill and habit to get used to.

The entire code for this walkthrough is available on Github here. Feel free to play around with it.

Skål!