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
相关产品推荐
相关产品推荐

