Symfony中模拟TokenStorageInterface返回User对象的测试问题求助
问题原因及解决方案
1. 报错原因
你遇到的Call to a member function getUser() on null报错和测试库的用户毫无关系,问题出在Mock对象的行为没有正确配置:
你通过$this->createMock(TokenStorageInterface::class)创建的模拟对象,所有方法默认返回null,你没有给getToken()方法配置返回值,调用$tokenStorage->getToken()自然返回null,再调用getUser()就会抛出错误。
2. 现有测试方式的问题
你当前写的测试逻辑是错误的,没有实际意义:
- 你模拟了
UserRepository但完全没有用到,你的原业务逻辑里也没有调用用户仓库的代码,属于无效Mock - 你当前的测试只是在验证「你自己配置的Mock返回你指定的对象」,没有验证你要测的业务逻辑(持久化用户实体那段)的正确性
3. 正确的测试实现
首先要按依赖关系逐层配置Mock,再把Mock注入到你要测的业务服务中,针对两个业务场景编写测试用例:
测试代码示例
public function testPersistMyEntityWithLoginUser() { // 1. 构造测试用户 $testUser = new User(); $testUser->setFirstName('测试用户'); // 2. 模拟Token对象,配置getUser返回测试用户 $token = $this->createMock(TokenInterface::class); $token->method('getUser') ->willReturn($testUser); // 3. 模拟TokenStorage,配置getToken返回上面的模拟Token $tokenStorage = $this->createMock(TokenStorageInterface::class); $tokenStorage->method('getToken') ->willReturn($token); // 4. 把模拟的TokenStorage注入到你要测的业务服务中 $targetService = new YourTargetService($tokenStorage); // 调用业务服务里包含持久化逻辑的方法 $result = $targetService->yourBusinessMethod(); // 5. 验证业务逻辑符合预期 $this->assertInstanceOf(MyEntity::class, $result); $this->assertEquals($testUser, $result->getUserId()); $this->assertEquals('测试用户', $result->getUserFirstName()); } // 补充未登录场景的测试 public function testPersistMyEntityWithAnonymousUser() { // 1. 模拟Token返回匿名用户标识 $token = $this->createMock(TokenInterface::class); $token->method('getUser') ->willReturn('anon.'); // 2. 模拟TokenStorage $tokenStorage = $this->createMock(TokenStorageInterface::class); $tokenStorage->method('getToken') ->willReturn($token); // 3. 调用业务方法 $targetService = new YourTargetService($tokenStorage); $result = $targetService->yourBusinessMethod(); // 4. 验证匿名场景的逻辑 $this->assertNull($result->getUserId()); $this->assertEquals('Unknown user', $result->getUserFirstName()); }
4. 测试用户复用问题
可以复用,你可以把构造测试用户的逻辑抽到测试类的setUp()方法中,或者封装为测试类的私有方法,所有需要用到测试用户的用例都可以直接调用获取,多场景测试也可以配合PHPUnit的数据供给器实现参数化传入不同的用户属性。
内容的提问来源于stack exchange,提问作者makeda202
相关产品推荐
相关产品推荐

