PHPUnit 测试中 Yii2 中的模拟视图助手

Posted

技术标签:

【中文标题】PHPUnit 测试中 Yii2 中的模拟视图助手【英文标题】:Mock view helper in Yii2 in PHPUnit test 【发布时间】:2020-08-15 23:36:20 【问题描述】:

我想在 Yii2 框架中测试一个特定的控制器动作。这个动作渲染视图文件使用了 helper yii\helpers\Url:

Url::toRoute('page')

当单元测试调用此视图时出现错误:

yii\base\InvalidArgumentException: Unable to resolve the relative route: vendor/bin/. No active controller is available.

测试:


<?php

use app\modules\user\controllers\UserController;

class UserControllerTest extends \PHPUnit_Framework_TestCase

    public function testActionIndex() 

        Yii::configure(Yii::$app, [
            'components' => [
                'user' => [
                    'class' => 'yii\web\User',
                    'identityClass' => 'app\modules\user\models\User',
                ],
                'request' => [
                    'class' => 'yii\web\Request',
                    'cookieValidationKey' => 'abc',
                ],
            ],
        ]);

        $controller = new UserController('user', Yii::$app);
        $result = $controller->run('index', []);
    

如何模拟方法 Url::toRoute 以避免此错误?

【问题讨论】:

你不能真正模拟静态方法而不改变源。有一些技巧可以做到这一点,但它们都是基于间接调用源代码中的静态方法。单元测试实际上并不是为了测试控制器的动作而设计的,最好对它们使用功能测试。如果您绝对必须对控制器的操作进行单元测试,您可以扩展您的 UserController 并覆盖 render() 方法以返回一些虚拟字符串而不是实际渲染。 我不知道 Yii 框架,但是你可以使用 \Mockery::mock('alias:ClassWhichContainsStaticMethod') 【参考方案1】:

Url 助手使用Yii::$app-&gt;controller 来解析相对路由。您需要在调用操作之前设置Yii::$app-&gt;controller

Yii::$app->controller = new UserController('user', Yii::$app);
$result = Yii::$app->controller->run('index', []);

您也可以使用绝对路由来避免这个问题:

Url::toRoute('/mymodule/mycontroller/page');

虽然这很不切实际,因为您需要在许多地方重复相同的路线。

【讨论】:

以上是关于PHPUnit 测试中 Yii2 中的模拟视图助手的主要内容,如果未能解决你的问题,请参考以下文章

如何在 PHPUnit 中跨多个测试模拟测试 Web 服务?

使用 Laravel 和 PHPUnit 模拟函数

PHPUnit:如何通过测试方法模拟内部调用的函数

YII2中的Html助手和Request组件

Laravel / PHPUnit:运行测试时没有模拟类

如何在 PHPUnit / Laravel 中模拟 JSON 文件