Laravel中如何测试PATCH方法?实体更新测试未生效排查
解决Laravel中PATCH更新方法的测试问题
问题场景
在Laravel中测试Product实体的PATCH更新接口时,测试用例无报错通过,但数据库中的数据并未更新为传入的新值。测试流程为:通过工厂创建Product实例,以认证用户身份调用patch()方法传入更新数据,最后查询数据库发现数据仍为初始值。
测试代码
public function test_check_count_additional_photos() { $product = Product::factory()->create(); $this->actingAs($this->user)->patch(route('editProduct', ['id' => $this->user->id, 'product' => $product->id]), [ 'title' => 'Updated product', 'description' => 'Updated Product description', 'price' => 1000, 'visible' => true, ]); dd(Product::all()) }
控制器代码
public function editProduct(int $userId, Product $product, UpdateProductRequest $request) { $product->title = isset($request->title) ? $request->title : $product->title; $product->description = isset($request->description) ? $request->description : $product->description; $product->price = isset($request->price) ? $request->price : $product->price; $product->visible = isset($request->visible) ? 1 : 0; $product->user_id = $userId; $product->update(); }
排查与解决方案
1. 路由参数匹配校验
检查editProduct路由的定义,确保路由参数名与控制器方法参数对应。控制器方法接收的是$userId和$product,但测试中route()传入的参数是['id' => $this->user->id, 'product' => $product->id],如果路由定义的参数名是user而非id,会导致控制器拿到错误的用户ID,甚至匹配到错误的Product实例。
修改测试中的路由参数为与路由定义一致的名称,例如:
route('editProduct', ['user' => $this->user->id, 'product' => $product->id])
2. 请求验证规则检查
查看UpdateProductRequest的验证规则,确认title、description、price、visible等字段是否被允许通过,是否存在required或其他规则导致请求数据被过滤。若验证未通过,控制器不会执行更新逻辑,但测试可能未捕获到错误。
在测试中添加断言验证请求无错误:
$this->assertSessionHasNoErrors();
3. 控制器逻辑优化
- 字段赋值逻辑问题:
isset($request->title)无法正确识别空字符串等合法值,改用$request->input('字段名', 默认值)简化赋值,同时确保布尔值处理准确:
public function editProduct(int $userId, Product $product, UpdateProductRequest $request) { $product->title = $request->input('title', $product->title); $product->description = $request->input('description', $product->description); $product->price = $request->input('price', $product->price); $product->visible = $request->boolean('visible'); $product->user_id = $userId; $product->save(); }
或直接使用fill()批量赋值(需确保模型的$fillable属性包含这些字段):
$product->fill($request->only(['title', 'description', 'price', 'visible']))->save();
- 模型权限校验:检查Product模型是否有全局作用域或策略限制,确保当前认证用户有权限更新该Product实例。
4. 测试用例规范优化
Laravel测试默认开启事务,测试结束后会回滚数据,使用dd()可能无法看到真实的更新结果。改用断言验证数据库数据:
public function test_check_count_additional_photos() { $product = Product::factory()->create(); $this->actingAs($this->user)->patch(route('editProduct', ['user' => $this->user->id, 'product' => $product->id]), [ 'title' => 'Updated product', 'description' => 'Updated Product description', 'price' => 1000, 'visible' => true, ]); // 断言数据库中存在更新后的数据 $this->assertDatabaseHas('products', [ 'id' => $product->id, 'title' => 'Updated product', 'price' => 1000, 'visible' => 1, ]); // 或刷新实例后断言属性 $updatedProduct = $product->refresh(); $this->assertEquals('Updated product', $updatedProduct->title); }
内容的提问来源于stack exchange,提问作者ШайтанЯкубович
相关产品推荐
相关产品推荐

