You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.30 12:45:00