当我使用标志覆盖率运行 Phpunit 时,出现错误:未定义的变量工厂

Posted

技术标签:

【中文标题】当我使用标志覆盖率运行 Phpunit 时,出现错误:未定义的变量工厂【英文标题】:When I run Phpunit with the flag coverage, the error appear: Undefined variable factory 【发布时间】:2020-03-06 02:30:44 【问题描述】:

我使用框架 Laravel 和包 modularization。

我创建了一个模块并对其进行了一些测试。但是,我无法在覆盖范围内运行测试 (./vendor/bin/phpunit --coverage-text --colors=never)。如果没有覆盖标志,测试运行正常 (./vendor/bin/phpunit)。

这是执行的两个命令:

在我所有的测试中,有一个测试叫工厂

class InstitutionControllerTest extends TestCase

    /**
     * @testdox Get the data of institutions
     * @covers \Modules\Institution\Http\Controllers\InstitutionController::index
     * */
    public function testIndex():void
    
        $institution = factory(Institution::class)->make();
        $institutionCollection = new Collection($institution);
        $mock = Mockery::mock(InstitutionRepository::class);
        $mock->shouldReceive('all')->andReturn($institutionCollection);
        $this->app->instance(InstitutionRepository::class, $mock);
        $response = $this->json('GET', 'api/institutions');
        $this->assertEquals(Response::HTTP_OK, $response->status());
        $this->assertEquals($institutionCollection, $response->getContent());
    

我按照documentation 中的说明将工厂添加到提供中,但它不能修复错误。

class InstitutionServiceProvider extends ServiceProvider

    public function boot()
    
       ...
        $this->registerFactories();
       ...
    
    public function register()
    
        $this->app->register(RouteServiceProvider::class);
        $this->app->singleton(Factory::class, function () 
            $faker = $this->app->make(\Faker\Generator::class);
            return Factory::construct($faker, __DIR__ . '/../Database/factories');
        );
    
...
    public function registerFactories()
    
        if (! app()->environment('production') && $this->app->runningInConsole()) 
            app(Factory::class)->load(__DIR__ . '/../Database/factories');
        
    
....

你知道我该如何解决这个错误吗?

phpunit.xml

<?xml version="1.0" encoding="UTF-8"?>
<phpunit backupGlobals="false"
         backupStaticAttributes="false"
         bootstrap="vendor/autoload.php"
         colors="true"
         convertErrorsToExceptions="true"
         convertNoticesToExceptions="true"
         convertWarningsToExceptions="true"
         processIsolation="false"
         stopOnFailure="false">
    <testsuites>
        <testsuite name="Unit">
            <directory suffix="Test.php">./tests/Unit/</directory>
            <directory suffix="Test.php">./Modules/**/Tests/Unit/</directory>
        </testsuite>

        <testsuite name="Feature">
            <directory suffix="Test.php">./tests/Feature/</directory>
            <directory suffix="Test.php">./Modules/**/Tests/Feature</directory>
        </testsuite>
    </testsuites>
    <filter>
        <whitelist processUncoveredFilesFromWhitelist="true">
            <directory suffix=".php">./app</directory>
            <directory suffix=".php">./Modules</directory>
            <exclude>
                <directory suffix="blade.php">./Modules</directory>
                <directory suffix=".php">./Modules/**/Routes</directory>
                <directory suffix=".php">./Modules/**/Resources</directory>
                <directory suffix=".php">./Modules/**/Tests</directory>
                <directory suffix=".php">./Modules/**/Config</directory>
            </exclude>
        </whitelist>
    </filter>
    <php>
        <server name="APP_ENV" value="testing"/>
        <server name="BCRYPT_ROUNDS" value="4"/>
        <server name="CACHE_DRIVER" value="array"/>
        <server name="MAIL_DRIVER" value="array"/>
        <server name="QUEUE_CONNECTION" value="sync"/>
        <server name="SESSION_DRIVER" value="array"/>
    </php>
</phpunit>

我的工厂班

<?php

/** @var \Illuminate\Database\Eloquent\Factory $factory */

use Faker\Generator as Faker;
use Modules\Institution\Entities\Institution;

// the variable $factory is Undefined
$factory->define(Institution::class, function (Faker $faker) 
    return [
        'name' => $faker->company
    ];
);

【问题讨论】:

【参考方案1】:

你的机器上安装了 Xdebug 吗?

要生成代码覆盖率,Php Unit 是不够的,它需要 Xdebug

【讨论】:

【参考方案2】:

将这些标志添加到您的测试 CLI 运行命令中

   --strict-coverage
   --verbose
   --stop-on-defect            
   --stop-on-error             
   --stop-on-failure           
   --stop-on-warning

更多信息available flags

在测试源中搜索前面不带美元符号的factory

您也可以通过使用这些标志来缩小生成此警告的范围

--group

--filter

有选择地运行测试,看看究竟是什么测试方法产生了这个警告。

对于组只需在所有测试方法中添加注释@group one@group two 等并使用标志运行测试

--group one

运行带有注解@group one的测试方法。

【讨论】:

我在命令中添加了标志,但它不起作用,我有同样的错误。另外,我在整个项目中搜索了 factory 变量,没有出现语法错误(例如,查看 factory 前面是否没有$)。你认为这可能是我的phpunit.xml 文件的错误吗? 我发现错误来自哪里,它是在我创建工厂类时出现的。但我不知道解决这个问题 @diego 编辑您的问题并添加工厂代码 + 准确标记问题出现的位置。

以上是关于当我使用标志覆盖率运行 Phpunit 时,出现错误:未定义的变量工厂的主要内容,如果未能解决你的问题,请参考以下文章

默认情况下在PHPUnit中运行单个测试套件

尝试使用Internet Explorer 11 / IE11运行Codeception / Selenium时的PHPUnit_Framework_Exception

PHPUnit错误未定义变量

如何更新 phpunit 6 和代码覆盖率 5

markdown [代码覆盖率Phpunit]安装Xdebug并使用Phpunit运行代码覆盖率#xdebug #phpunit #code #coverage

Laravel 5:PHPUnit 和没有可用的代码覆盖驱动程序