应继承HyperfTestTestCase基类,它在setUp中自动初始化完整DI容器(含AnnotationScanner、DefinitionLoader等),手动new Container或extend PHPUnit\Framework\TestCase会导致@Inject失效。

单元测试里 $this->container 是 null 怎么办
Hyperf 的单元测试默认不自动初始化 DI 容器,$this->container 为 null 是常态,不是你写错了。测试类必须显式继承 HyperfTestTestCase 或手动构建容器实例。
常见错误现象:Call to a member function get() on null,或注入的属性始终为 null。
- Hyperf 提供的基类是
HyperfTestTestCase(位于HyperfTestTestCase),它会在setUp()中调用ApplicationContext::setContainer()并初始化完整容器 - 不要自己 extend
PHPUnit\Framework\TestCase后手动 new Container——缺了 AnnotationScanner、DefinitionLoader 等关键组件,@Inject依然不会生效 - 若需自定义测试基类,必须复刻
HyperfTestTestCase::setUp()中的容器初始化逻辑,尤其是DiFactory::createContainer()和ApplicationContext::setContainer()两步缺一不可
@Inject 在测试中不触发,是不是注解没扫到
是。即使继承了正确基类,如果被测类不在扫描路径内,或未带有效注解,@Inject 仍不会被处理。
- 确认被测类(如
UserService)在config/autoload/annotations.php的scan.paths中,且路径真实存在(例如BASE_PATH . '/app') - 类上至少有一个“可激活扫描”的注解,如
#[Service]、#[Controller]或#[Aspect];仅带#[Inject]的普通类不会被自动注册 - 运行
php bin/hyperf.php di:dump查看容器中是否已注册该类;若没有,说明扫描失败,不是注入逻辑问题 - 测试中不要用
new UserService()实例化对象——它脱离容器管理,@Inject完全失效
测试中手动获取服务时提示 “Entry cannot be resolved”
容器里确实没这个类,原因通常是绑定缺失或类型不匹配。
- 接口未绑定实现:比如你要
$container->get(LoggerInterface::class),但dependencies.php里没写LoggerInterface::class => Logger::class - 绑定用了字符串键而非 FQCN:错误写法
'logger' => Logger::class,正确应为LoggerInterface::class => Logger::class - 测试环境配置未加载:检查
phpunit.xml中是否设置了HYPERF_ENV=testing,并确认config/autoload/dependencies/testing.php(如有)被正确合并 - 避免在测试中依赖
ApplicationContext::getContainer()->get()前未执行DiFactory::init()——HyperfTestTestCase已封装此逻辑,自行构造容器时容易漏掉
为什么 #[PostConstruct] 在测试中不执行
因为 PostConstruct 是 AOP 代理行为,而默认测试不会生成代理类。
-
#[PostConstruct]依赖代理类注入逻辑,必须确保被测类已被 AOP 处理:类上要有#[Service]等注解,且di:proxy:generate已运行(或启用了自动代理) - 测试环境下 runtime 目录常被忽略,
runtime/container/proxy/下无对应$$Proxy文件 →#[PostConstruct]静默跳过 - 临时解决:在测试 setUp 中手动调用
$instance->__postConstruct()(不推荐长期使用) - 根本解法:确保测试运行前已生成代理,或改用构造函数注入替代
#[PostConstruct]初始化逻辑
最易被忽略的一点:Hyperf 测试容器和运行时容器不是同一个实例,哪怕你手动 setContainer,也不会自动加载注解扫描结果或代理类——所有初始化必须走 HyperfTestTestCase 的标准流程,绕不开。


















