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

PHPUnit测试Twig模板时如何mock父模板base.html.twig仅测试子模板

PHPUnit中Mock Twig父模板测试子模板的解决方案

你可以通过以下两种常用方案实现仅测试子模板内容,不需要依赖真实的base.html.twig:

方法一:使用ChainLoader覆盖父模板(通用稳定方案)

原理是给Twig实例添加优先级更高的数组加载器,把base.html.twig指向我们自定义的mock模板,规避加载真实父模板。

注意:标准Twig语法要求继承父模板的子模板,所有需要渲染的内容必须放在{% block %}标签内,否则非块级内容会被自动忽略。建议先调整子模板结构:

{% extends 'base.html.twig' %}
{% block body %}
<html>
     <p>The status of user!</p>;
</html>
{% endblock %}

测试代码示例:

$expected = <<<HTML
<html>
     <p>The status of user!</p>;
</html>
HTML;

self::bootKernel();
$container = self::$kernel->getContainer();
/** @var \Twig\Environment $twig */
$twig = $container->get('twig');

// 构造mock父模板,直接输出子模板的body块内容
$arrayLoader = new \Twig\Loader\ArrayLoader([
    'base.html.twig' => '{{ block(\'body\') }}',
]);
// 组合链式加载器,数组加载器优先级高于原加载器
$chainLoader = new \Twig\Loader\ChainLoader([
    $arrayLoader,
    $twig->getLoader()
]);
$twig->setLoader($chainLoader);

$actual = $twig->render('user-test.html.twig');
$this->assertEquals(trim($expected), trim($actual));

方法二:直接渲染处理后的子模板源码(轻量快速方案)

如果不想调整模板结构和加载器,可以直接读取子模板源码、移除继承语句后渲染:

$expected = <<<HTML
<html>
     <p>The status of user!</p>;
</html>
HTML;

self::bootKernel();
$container = self::$kernel->getContainer();
/** @var \Twig\Environment $twig */
$twig = $container->get('twig');

// 读取子模板源码并移除extends语句
$templateSource = $twig->getLoader()->getSourceContext('user-test.html.twig')->getCode();
$templateWithoutExtends = preg_replace('/{% extends\s+[\'"].+?[\'"]\s+%}/', '', $templateSource);

// 直接渲染处理后的模板内容
$actual = $twig->createTemplate($templateWithoutExtends)->render();
$this->assertEquals(trim($expected), trim($actual));

注意:方法二会忽略所有继承相关逻辑,如果子模板中有调用{{ parent() }}、依赖父模板的变量/宏,会出现渲染错误,需要提前处理对应逻辑。

内容的提问来源于stack exchange,提问作者makeda202

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 14:24:07