如何正确Mock Laravel模型以测试关联用户创建业务逻辑
前置操作:修复业务代码拼写错误
你提供的业务代码存在2处变量大小写不一致的问题,会直接导致运行报错,请先修正:
__invoke方法中,$this->updateUserUser2Id($user2->id);修改为$this->updateUserUser2Id($User2->id);updateUser2UsernameWithId方法中,参数声明为User2 $User2,方法体内所有$user2统一修改为$User2
测试实现方案
核心思路
- 对于
User对象,直接使用带属性预赋值的部分Mock即可,无需手动处理魔术方法__get的返回逻辑,避免属性访问报错 - 对于
User2的静态调用create,使用别名Mock实现静态方法的调用验证 - 私有方法
generateUser2Username的逻辑无需直接调用,通过断言User2::create接收的username参数即可间接验证逻辑正确性
完整测试代码
use App\User; use App\Page\Actions\CreateUser2ForUserAction; use App\Models\Shops\User2; use Mockery; class CreateUser2ForUserActionTest extends \Tests\TestCase { public function test_action_executes_as_expected() { // 1. 构造测试基础数据 $testUserName = 'Joe Bloggs'; $testUserEmail = 'joe@example.com'; $testUser2Id = 123; $expectedInitUsername = 'JoeBlo'; // generateUser2Username的预期输出 $expectedFinalUsername = $expectedInitUsername . $testUser2Id; // 2. Mock User对象,预赋值属性,配置save方法期望 $mockUser = Mockery::mock(User::class)->makePartial(); $mockUser->name = $testUserName; $mockUser->email = $testUserEmail; $mockUser->shouldReceive('save') ->once() ->andReturn(true); // 3. Mock User2实例,配置属性和save方法期望 $mockUser2Instance = Mockery::mock(User2::class)->makePartial(); $mockUser2Instance->id = $testUser2Id; $mockUser2Instance->shouldReceive('save') ->once() ->andReturn(true); // 4. Mock User2静态create方法,验证入参 Mockery::mock('alias:' . User2::class) ->shouldReceive('create') ->once() ->with([ 'username' => $expectedInitUsername, 'email' => $testUserEmail, 'user_type' => CreateUser2ForUserAction::A_USER_TYPE ]) ->andReturn($mockUser2Instance); // 5. 执行业务逻辑 $action = new CreateUser2ForUserAction(); $resultUser = $action($mockUser); // 6. 后置断言 // 验证User对象user2_id被正确赋值 $this->assertEquals($testUser2Id, $resultUser->user2_id); // 验证User2对象最终username被正确修改 $this->assertEquals($expectedFinalUsername, $mockUser2Instance->username); } protected function tearDown(): void { parent::tearDown(); Mockery::close(); // 清理Mockery实例避免污染其他测试 } }
测试点覆盖说明
- ✅
generateUser2Username逻辑验证:通过User2::create的入参username为预期的JoeBlo,间接验证私有方法逻辑正确 - ✅
User2::create入参验证:Mock时指定with参数,不匹配会直接抛出测试失败 - ✅
User2::save调用验证:Mock实例配置save方法调用次数期望 - ✅
User::save调用验证:Mock User实例配置save方法调用次数期望 - ✅
User.user2_id赋值验证:执行完成后直接断言User对象的user2_id属性等于Mock的User2ID
内容的提问来源于stack exchange,提问作者devvvvvvvvvvvvvv
相关产品推荐
相关产品推荐

