Laravel 5.6中如何用PHPUnit和Mockery测试仓库模式update方法
为Laravel PackageController编写testUpdate()测试(PHPUnit + Mockery)
看起来你已经搞定了testIndex(),现在要写testUpdate()对吧?没问题,我来一步步教你怎么实现。我们的目标是验证PackageController的update方法是否正确调用了PackageInterface的updatePackage方法,并且返回预期的重定向响应。
步骤1:明确测试核心目标
我们只需要验证两件关键事:
PackageController@update会正确调用PackageInterface::updatePackage,传入符合要求的package_id参数- 方法执行完成后,会返回
redirect()->back()的重定向响应
步骤2:编写完整的testUpdate()代码
直接上可运行的测试代码,我会逐行解释逻辑:
public function testUpdate() { // 1. 准备测试用的包ID,选一个合理的数值即可 $packageId = 1; // 2. 模拟一个更新后的Package模型实例(可选,但让测试逻辑更完整) // 注:Controller的update方法不会使用这个返回值,所以简单Mock即可 $mockPackage = \Mockery::mock(\App\Models\Package::class); // 3. 设定Mock接口的预期行为: // 要求updatePackage方法被调用1次,参数必须是我们指定的$packageId,返回模拟的模型 $this->mock ->shouldReceive('updatePackage') ->once() ->with($packageId) ->andReturn($mockPackage); // 4. 调用Controller的update方法 $response = $this->target->update($packageId); // 5. 断言返回的是符合预期的重定向响应 $this->assertInstanceOf(\Illuminate\Http\RedirectResponse::class, $response); $this->assertEquals(302, $response->getStatusCode()); // 验证重定向状态码 $this->assertEquals(url()->previous(), $response->getTargetUrl()); // 验证重定向目标是上一页 }
步骤3:关键细节解释
- Mock的自动验证:
shouldReceive('updatePackage')->once()会在测试结束时自动验证这个方法是否真的被调用了一次,如果调用次数不对或者没被调用,PHPUnit会直接抛出错误,不用额外写断言。 - 为什么不需要模拟Request? 因为我们Mock的是
PackageInterface,Controller调用的是Mock的updatePackage方法,而非实际PackageRepository的实现,所以Repository内部依赖的Request逻辑在这个测试里不会被触发。如果要验证PackageRepository的updatePackage逻辑,需要单独编写单元测试。
额外补充:测试PackageRepository的updatePackage方法(可选)
如果需要验证仓库层的业务逻辑是否正确,可以编写对应的单元测试,示例如下:
// Tests/Unit/PackageRepositoryTest.php namespace Tests\Unit; use Tests\TestCase; use App\Repositories\PackageRepository; use App\Models\Package; use Illuminate\Http\Request; class PackageRepositoryTest extends TestCase { public function testUpdatePackage() { // 1. 创建测试用的Package实例并写入数据库 $package = Package::factory()->create(['description' => '旧描述']); // 2. 模拟包含新描述的Request $request = Request::create('/packages/' . $package->id, 'PUT', [ 'description' => '更新后的新描述' ]); // 3. 实例化Repository,注入依赖 $repository = new PackageRepository($request, new Package()); // 4. 调用updatePackage方法 $updatedPackage = $repository->updatePackage($package->id); // 5. 断言描述被正确更新 $this->assertEquals('更新后的新描述', $updatedPackage->description); // 断言数据库中的数据也同步更新 $this->assertDatabaseHas('packages', [ 'id' => $package->id, 'description' => '更新后的新描述' ]); } }
内容的提问来源于stack exchange,提问作者Memo Chou
相关产品推荐
相关产品推荐

