Back to Course |
Testing in Laravel 9 For Beginners: PHPUnit, Pest, TDD

Update Product: test if validation error is fired correctly

Now that we have an edit form, let's test that validation works.


Laravel Code

Again, first, the working code.

php artisan make:request UpdateProductRequest

app/Http/Requests/UpdateProductRequest.php:

use Illuminate\Foundation\Http\FormRequest;
 
class UpdateProductRequest extends FormRequest
{
public function authorize(): bool
{
return true;
}
 
public function rules(): array
{
return [
'name' => 'required',
'price' => 'required',
];
}
}

app/Http/Controllers/ProductController.php:

use Illuminate\Http\RedirectResponse;
use App\Http\Requests\UpdateProductRequest;
 
class ProductController extends Controller
{
// ...
 
public function update(UpdateProductRequest $request, Product $product): RedirectResponse
{
$product->update($request->validated());
 
return redirect()->route('products.index');
}
}

The Test

The PUT request is used for updating, so in the test, again acting as an admin, we send a PUT request with empty values.

tests/Feature/ProductsTest.php:

class ProductsTest extends TestCase
{
// ...
 
public function test_product_update_validation_error_redirects_back_to_form()
{
$product = Product::factory()->create();
 
$response = $this->actingAs($this->admin)->put('products/' . $product->id, [
'name' => '',
'price' => ''
]);
}
 
private function createUser(bool $isAdmin = false): User
{
return User::factory()->create([
'is_admin' => $isAdmin,
]);
}
}

And now, we need to assert. We can first assert that the response is a redirect. And then Laravel has an assertion just for validatiing errors assertInvalid.

tests/Feature/ProductsTest.php:

class ProductsTest extends TestCase
{
// ...
 
public function test_product_update_validation_error_redirects_back_to_form()
{
$product = Product::factory()->create();
 
$response = $this->actingAs($this->admin)->put('products/' . $product->id, [
'name' => '',
'price' => ''
]);
}
 
private function createUser(bool $isAdmin = false): User
{
return User::factory()->create([
'is_admin' => $isAdmin,
]);
 
$response->assertStatus(302);
$response->assertInvalid(['name', 'price']);
}
}

Another assertion to assert validation can be used is assertSessionHasErrors. In the same way as in assertInvalid, we need to provide keys.

tests/Feature/ProductsTest.php:

class ProductsTest extends TestCase
{
// ...
 
public function test_product_update_validation_error_redirects_back_to_form()
{
$product = Product::factory()->create();
 
$response = $this->actingAs($this->admin)->put('products/' . $product->id, [
'name' => '',
'price' => ''
]);
}
 
private function createUser(bool $isAdmin = false): User
{
return User::factory()->create([
'is_admin' => $isAdmin,
]);
 
$response->assertStatus(302);
$response->assertInvalid(['name', 'price']);
$response->assertSessionHasErrors(['name', 'price']);
}
}

edit product form validation test


Commit for this lesson