{"id":13540,"date":"2023-11-28T10:00:00","date_gmt":"2023-11-28T01:00:00","guid":{"rendered":"https:\/\/www.gigas-jp.com\/appnews\/?p=13540"},"modified":"2023-11-27T19:42:58","modified_gmt":"2023-11-27T10:42:58","slug":"writing-user-crud-api-feature-test-in-laravel","status":"publish","type":"post","link":"https:\/\/www.gigas-jp.com\/appnews\/archives\/13540","title":{"rendered":"Writing User CRUD API Feature Test in Laravel"},"content":{"rendered":"\n<p>Laravel&nbsp;empowers developers to build efficient and robust APIs effortlessly. Feature testing is an indispensable aspect of ensuring the reliability and functionality of our APIs, especially when it involves user CRUD operations. In this blog post, we&#8217;ll take a step-by-step journey through the code to feature test a User CRUD API in Laravel.<\/p>\n\n\n\n<p><strong>Step 1: Setting Up the Test Environment<\/strong><\/p>\n\n\n\n<p>Create a test class file with the following command.  <\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>php artisan make:test UserCrudApiTest<\/code><\/pre>\n\n\n\n<p><\/p>\n\n\n\n<p>The test class file created can be found at <code>tests\/Feature\/UserCrudApiTest.php<\/code> and codes are as follows.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;?php\n\nnamespace Tests\\Feature;\n\nuse Illuminate\\Foundation\\Testing\\RefreshDatabase;\nuse Illuminate\\Foundation\\Testing\\WithFaker;\nuse Tests\\TestCase;\n\nclass UserCrudApiTest extends TestCase\n{\n    \/**\n     * A basic feature test example.\n     *\n     * @return void\n     *\/\n    public function test_example()\n    {\n        $response = $this-&gt;get('\/');\n\n        $response-&gt;assertStatus(200);\n    }\n}<\/code><\/pre>\n\n\n\n<p><\/p>\n\n\n\n<p><strong>Step 2: Define and modify the Test Class<\/strong><\/p>\n\n\n\n<p>Import necessary classes and traits. And remove default test_example method.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;?php\n\nnamespace Tests\\Feature;\nuse Illuminate\\Foundation\\Testing\\RefreshDatabase;\nuse Illuminate\\Foundation\\Testing\\WithFaker;\nuse Tests\\TestCase;\nuse App\\Models\\User;\n\nclass UserCrudApiTest extends TestCase\n{\n    use RefreshDatabase;\n}<\/code><\/pre>\n\n\n\n<p><\/p>\n\n\n\n<p>The `UserCrudApiTest` class is declared, extending `TestCase` and using `RefreshDatabase` for database isolation.<\/p>\n\n\n\n<p>`RefreshDatabase` ensures a clean database state for each test, and `TestCase` is the base test case class. `User` is imported to create and interact with user models.<\/p>\n\n\n\n<p><strong>Step 3: Testing User Creation<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>public function test_user_can_be_created()\n{\n    $userData = &#091;\n        'name' =&gt; 'John Doe',\n        'email' =&gt; 'john@example.com',\n        'password' =&gt; bcrypt('password123'),\n    ];\n\n    $response = $this-&gt;json('POST', '\/api\/users', $userData);\n\n    $response-&gt;assertStatus(201)\n             -&gt;assertJson(&#091;\n                 'name' =&gt; 'John Doe',\n                 'email' =&gt; 'john@example.com',\n             ]);\n\n    $this-&gt;assertDatabaseHas('users', &#091;\n        'name' =&gt; 'John Doe',\n        'email' =&gt; 'john@example.com',\n    ]);\n}<\/code><\/pre>\n\n\n\n<p><\/p>\n\n\n\n<p>This method tests the creation of a user. The `$this-&gt;json(&#8216;POST&#8217;, &#8216;\/api\/users&#8217;, $userData)` line sends a POST request to create a user with the specified data. Assertions ensure a successful response, correct JSON structure, and that the user is stored in the database.<\/p>\n\n\n\n<p><strong>Step 4: Testing User Retrieval<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>public function test_user_can_be_retrieved()\n{\n    $user = factory(User::class)-&gt;create();\n\n    $response = $this-&gt;json('GET', \"\/api\/users\/{$user-&gt;id}\");\n\n    $response-&gt;assertStatus(200)\n             -&gt;assertJson(&#091;\n                 'name' =&gt; $user-&gt;name,\n                 'email' =&gt; $user-&gt;email,\n             ]);\n}<\/code><\/pre>\n\n\n\n<p><\/p>\n\n\n\n<p>This method tests the retrieval of a user. A user is created using the factory, and a GET request is made to fetch the user&#8217;s details. Assertions verify a successful response and the correctness of the returned data.<\/p>\n\n\n\n<p><strong>Step 5: Testing User Update<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>public function test_user_can_be_updated()\n{\n    $user = factory(User::class)-&gt;create();\n\n    $updateData = &#091;\n        'name' =&gt; 'Updated Name',\n        'email' =&gt; 'updated.email@example.com',\n    ];\n\n    $response = $this-&gt;json('PUT', \"\/api\/users\/{$user-&gt;id}\", $updateData);\n\n    $response-&gt;assertStatus(200)\n             -&gt;assertJson($updateData);\n\n    $this-&gt;assertDatabaseHas('users', &#091;\n        'id' =&gt; $user-&gt;id,\n        'name' =&gt; 'Updated Name',\n        'email' =&gt; 'updated.email@example.com',\n    ]);\n}<\/code><\/pre>\n\n\n\n<p><\/p>\n\n\n\n<p>This method tests updating a user&#8217;s details. A user is created, and a PUT request updates the user&#8217;s data. Assertions check for a successful response, the correctness of the returned JSON, and the updated data in the database.<\/p>\n\n\n\n<p><strong>Step 6: Testing User Deletion<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>public function test_user_can_be_deleted()\n{\n    $user = factory(User::class)-&gt;create();\n\n    $response = $this-&gt;json('DELETE', \"\/api\/users\/{$user-&gt;id}\");\n\n    $response-&gt;assertStatus(204);\n\n    $this-&gt;assertDatabaseMissing('users', &#091;'id' =&gt; $user-&gt;id]);\n}<\/code><\/pre>\n\n\n\n<p><\/p>\n\n\n\n<p>This method tests the deletion of a user. A user is created, and a DELETE request is made to delete the user. Assertions ensure a successful response and confirm that the user is no longer present in the database.<\/p>\n\n\n\n<p>After writing the necessary test methods, we can test with the following artisan command.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>php artisan test --filter UserCrudApiTest<\/code><\/pre>\n\n\n\n<p><\/p>\n\n\n\n<p>This command uses the <code>--filter<\/code> option to specify a particular test class, in this case, <code>UserCrudApiTest<\/code>. Only the tests within the <code>UserCrudApiTest<\/code> class will be executed.<\/p>\n\n\n\n<p>The <code>--filter<\/code> option can also be used to run specific methods within a test class. For example:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>php artisan test --filter UserCrudApiTest::test_user_can_be_created<\/code><\/pre>\n\n\n\n<p><\/p>\n\n\n\n<p>Also <code>php artisan test<\/code> can be used to run all the tests in the application (all test files under <code>tests<\/code> dir).<\/p>\n\n\n\n<p><strong>Conclusion<\/strong><\/p>\n\n\n\n<p>Feature testing User CRUD operations in a Laravel API provides confidence in the functionality and reliability of the endpoints. Each step, from setup to testing each CRUD operation, contributes to a robust testing suite that helps maintain a high standard of code quality in our Laravel applications.<\/p>\n\n\n\n<p>Hope you enjoy that.<\/p>\n\n\n\n<p>Asahi<\/p>\n<div class='wp_social_bookmarking_light'>\n            <div class=\"wsbl_google_plus_one\"><g:plusone size=\"medium\" annotation=\"none\" href=\"https:\/\/www.gigas-jp.com\/appnews\/archives\/13540\" ><\/g:plusone><\/div>\n            <div class=\"wsbl_hatena_button\"><a href=\"\/\/b.hatena.ne.jp\/entry\/https:\/\/www.gigas-jp.com\/appnews\/archives\/13540\" class=\"hatena-bookmark-button\" data-hatena-bookmark-title=\"Writing User CRUD API Feature Test in Laravel\" data-hatena-bookmark-layout=\"standard\" title=\"\u3053\u306e\u30a8\u30f3\u30c8\u30ea\u30fc\u3092\u306f\u3066\u306a\u30d6\u30c3\u30af\u30de\u30fc\u30af\u306b\u8ffd\u52a0\"> <img src=\"\/\/b.hatena.ne.jp\/images\/entry-button\/button-only@2x.png\" alt=\"\u3053\u306e\u30a8\u30f3\u30c8\u30ea\u30fc\u3092\u306f\u3066\u306a\u30d6\u30c3\u30af\u30de\u30fc\u30af\u306b\u8ffd\u52a0\" width=\"20\" height=\"20\" style=\"border: none;\" \/><\/a><script type=\"text\/javascript\" src=\"\/\/b.hatena.ne.jp\/js\/bookmark_button.js\" charset=\"utf-8\" async=\"async\"><\/script><\/div>\n            <div class=\"wsbl_twitter\"><a href=\"https:\/\/twitter.com\/share\" class=\"twitter-share-button\" data-url=\"https:\/\/www.gigas-jp.com\/appnews\/archives\/13540\" data-text=\"Writing User CRUD API Feature Test in Laravel\" data-via=\"GIGASJAPAN_APPS\" data-lang=\"ja\">Tweet<\/a><\/div>\n            <div class=\"wsbl_facebook_like\"><div id=\"fb-root\"><\/div><fb:like href=\"https:\/\/www.gigas-jp.com\/appnews\/archives\/13540\" layout=\"button_count\" action=\"like\" width=\"100\" share=\"false\" show_faces=\"false\" ><\/fb:like><\/div>\n            <div class=\"wsbl_facebook_send\"><div id=\"fb-root\"><\/div><fb:send href=\"https:\/\/www.gigas-jp.com\/appnews\/archives\/13540\" colorscheme=\"light\" ><\/fb:send><\/div>\n    <\/div>\n<br class='wp_social_bookmarking_light_clear' \/>\n","protected":false},"excerpt":{"rendered":"<p>Laravel&nbsp;empowers developers to build efficient and robust APIs effortlessly. Feature testing is an indisp [&hellip;]<\/p>\n","protected":false},"author":20,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[100],"tags":[],"acf":[],"_links":{"self":[{"href":"https:\/\/www.gigas-jp.com\/appnews\/wp-json\/wp\/v2\/posts\/13540"}],"collection":[{"href":"https:\/\/www.gigas-jp.com\/appnews\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.gigas-jp.com\/appnews\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.gigas-jp.com\/appnews\/wp-json\/wp\/v2\/users\/20"}],"replies":[{"embeddable":true,"href":"https:\/\/www.gigas-jp.com\/appnews\/wp-json\/wp\/v2\/comments?post=13540"}],"version-history":[{"count":7,"href":"https:\/\/www.gigas-jp.com\/appnews\/wp-json\/wp\/v2\/posts\/13540\/revisions"}],"predecessor-version":[{"id":13548,"href":"https:\/\/www.gigas-jp.com\/appnews\/wp-json\/wp\/v2\/posts\/13540\/revisions\/13548"}],"wp:attachment":[{"href":"https:\/\/www.gigas-jp.com\/appnews\/wp-json\/wp\/v2\/media?parent=13540"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.gigas-jp.com\/appnews\/wp-json\/wp\/v2\/categories?post=13540"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.gigas-jp.com\/appnews\/wp-json\/wp\/v2\/tags?post=13540"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}