Kako zgraditi API Laravel REST s testnim razvojem

Obstaja slavni citat Jamesa Grenninga, enega od začetnikov razvojnih metodologij TDD in Agile:

Če se ne ukvarjate s testnim razvojem, se ukvarjate s kasnejšim razvojem - James Grenning

Danes se bomo odpravili na potovanje po Laravelu, ki ga vodijo testi. Ustvarili bomo Laravel REST API skupaj s preverjanjem pristnosti in CRUD funkcionalnostjo, ne da bi odprli Postman ali brskalnik. ?

Opomba: Ta navodila za uporabo predvidevajo, da razumete osnovne koncepte Laravel in PHPUnit. Če vam tega ni več na poti? Peljimo se.

Priprava projekta

Začnite z ustvarjanjem novega projekta Laravel z composer create-project --prefer-dist laravel/laravel tdd-journey.

Nato moramo zagnati avtentifikacijski oder, ki bi ga uporabili, php artisan make:authnato pa zaženite php artisan migrate.

Pravzaprav ne bomo uporabljali ustvarjenih poti in pogledov. Za ta projekt bi uporabili jwt-auth. Torej, nadaljujte in ga nastavite v svoji aplikaciji.

Opomba: Če imate napake z generateukazom JWT , lahko sledite temu popravku, dokler ni dodan v stabilno različico.

Končno, lahko izbrišete ExampleTestv obeh tests/Unitin tests/Featuremape, tako, da ne posega v naših testnih rezultatov in da smo na dobri poti.

Pisanje kode

  1. Začnite tako, da nastavite svojo authkonfiguracijo za uporabo privzetega gonilnika JWT:

Nato v routes/api.phpdatoteko dodajte naslednje :

2. Zdaj, ko imamo nastavljen gonilnik, nastavite svoj uporabniški model na enak način:

Kar smo storili, je bilo, da smo samo implementirali JWTSubjectin dodali zahtevane metode.

3. Nato moramo v krmilnik dodati metode preverjanja pristnosti.

Zaženite php artisan make:controller AuthControllerin dodajte naslednje metode:

Ta korak je lepo naravnost naprej, vse moramo storiti, je dodati authenticate, in registermetode za naš krmilnik. V authenticatemetodi preverimo vnos, poskusimo se prijaviti in vrnemo žeton, če je uspešen. Pri metodi registra potrdimo vnos, z vhodom ustvarimo novega uporabnika in na podlagi tega ustvarimo žeton za uporabnika.

4. Nato na dober del. Testiranje tega, kar smo pravkar napisali. Ustvari preskusne razrede z uporabo php artisan make:test AuthTest. V novem tests/Feature/AuthTestdodajte te metode:

Komentarji v zgornji kodi v veliki meri opisujejo kodo. Nekaj, na kar morate biti pozorni, je, kako uporabnika ustvarjamo in brišemo v vsakem testu. Bistvo testov je, da bi morali biti med seboj neodvisni in v idealnem primeru stanja baze podatkov.

Zdaj zaženite $vendor/bin/phpunitali $ phpunitče imate globalno nameščeno. Tek, ki bi vam dal uspešne trditve. Če temu ni bilo tako, si lahko ogledate dnevnike, popravite in znova preizkusite. To je čudovit cikel TDD.

5. Zdaj, ko preverjanje pristnosti deluje, dodajte element za CRUD. Za to vadnico bomo uporabili recepte za hrano kot CRUD izdelke, zakaj, zakaj ne?

Začnite z ustvarjanjem naše selitve php artisan make:migration create_recipes_tablein dodajte naslednje:

Nato zaženite selitev. Zdaj dodajte model z uporabo php artisan make:model Recipein dodajte to našemu modelu.

Nato to metodo dodajte v usermodel.

6. Zdaj potrebujemo končne točke za upravljanje naših receptov. Najprej bomo ustvarili krmilnik php artisan make:controller RecipeController. Nato uredite routes/api.phpdatoteko in dodajte createkončno točko.

V krmilnik dodajte tudi metodo ustvarjanja

Ustvarite preizkus funkcije z php artisan make:test RecipeTestvsebino in jo uredite kot spodaj:

Koda je precej samoumevna. Vse, kar naredimo, je ustvariti metodo, ki obravnava registracijo uporabnika in generiranje žetona, nato pa to žeton uporabimo v testCreate()metodi. Upoštevajte uporabo RefreshDatabaselastnosti, ki je Laravelov priročen način ponastavitve vaše baze podatkov po vsakem preizkusu, kar je kot nalašč za naš čudovit majhen projekt.

V redu, za zdaj želimo zatrditi le status odziva, pojdite naprej in zaženite $ vendor/bin/phpunit.

Če je vse v redu, se prikaže napaka. ?

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.

Če pogledamo dnevniške datoteke, lahko ugotovimo, da je krivec odnos publisherin recipesrazmerja v Recipein Userrazredih. Laravel poskuša najti user_idstolpec v tabeli in ga uporabiti kot tuji ključ, toda v naši selitvi smo nastavili publisher_idkot tuji ključ. Zdaj prilagodite vrstice kot spodaj:

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

In nato znova zaženite test. Če je vse v redu, dobimo vse zelene teste! ?

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

Zdaj moramo še preizkusiti ustvarjanje recepta. Za to lahko potrdimo število receptov uporabnika. Posodobite svojo testCreatemetodo kot spodaj:

Zdaj lahko nadaljujemo in izpolnimo ostale metode. Čas za nekaj sprememb. Najprej našaroutes/api.php

Nato metode dodamo krmilniku. Posodobite svoj RecipeControllerrazred na ta način.

Koda in komentarji logiko že razlagajo.

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.

Na zdravje!