【问题标题】:Laravel 8 Tests: PHPUnit error: Unknown formatter "unique"Laravel 8 测试:PHPUnit 错误:未知格式化程序“唯一”
【发布时间】:2021-03-10 03:34:49
【问题描述】:

我编写了一个涉及工厂的测试。当我执行测试时,我得到这个错误:

为 Tests\Unit\ExampleTest::testTakePlace 指定的数据提供程序无效。 InvalidArgumentException:未知格式化程序“唯一”/var/www/html/api/vendor/fakerphp/faker/src/Faker/Generator.php:249

预期结果

这个错误不应该显示,我应该可以使用$this->faker->unique()

我是如何解决这个问题的

通过一遍又一遍地阅读文档(没有发现差异)和阅读互联网上的问题和答案(只找到一个问题和一个答案:扩展 Laravel 的 TestCase 但官方文档,正如我提到的那样,说相反)。 (Laravel 的TestCaseuse Illuminate\Foundation\Testing\TestCase; 提供)

问题

为什么它不起作用以及如何修复这个错误?

来源

测试来源

它扩展了 PHPUnit\Framework\TestCase(不是 Laravel 的 TestCase),因为文档说要扩展它。确实:https://laravel.com/docs/8.x/testing#creating-and-running-tests。这不是文档中唯一提到扩展它的部分。

<?php

namespace Tests\Unit;

use PHPUnit\Framework\TestCase;
use App\Models\Project;

class ExampleTest extends TestCase
{
    /**
     * @dataProvider provideTakePlaceData
     */
    public function testTakePlace($project)
    {
        $response = $this->json('GET', '/controllerUserProject_takePlace', [
            'project_id' => $project->id
        ]);

        
    }
    
    public function provideTakePlaceData() {
        return [    
                    Project::factory()->make()
        ];
    }
}

控制器

<?php

namespace App\Http\Controllers;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;

class ControllerUserProject extends Controller
{
    public function takePlace(Request $request, $project_id)
    {
        return;
    }
}

最重要的:工厂

<?php

namespace Database\Factories;

use App\Models\Project;
use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Support\Str;

class ProjectFactory extends Factory
{
    /**
     * The name of the factory's corresponding model.
     *
     * @var string
     */
    protected $model = Project::class;

    /**
     * Define the model's default state.
     *
     * @return array
     */
    public function definition()
    {
        return [
                    'id' => $this->faker->unique()->numberBetween(1, 9000), 
        ];
    }
}

【问题讨论】:

  • 你应该从 Laravel 扩展 TestCase,这个 TestCase 还扩展了 PHPUnit\Framework\TestCase,所以你将拥有 Laravel 方法和 PhpUnit 方法。试试
  • 运行composer update 以确保一切都是最新的?如果此项目是在旧版本的 Laravel 中创建的,请确保您的 composer.json 已更新为与使用不同的 faker 库的 the latest one 匹配。
  • 我可以毫无问题地在我的工厂中使用相同的代码(尽管我没有;我只是让数据库自动增量为我处理主键。)你的问题花了这么多钱是有原因的吗测试方面的时间?工厂是否在其他情况下工作?
  • @miken32 你用了什么命令? php artisan test ?
  • 我只是单独测试工厂代码,但它看起来对你来说是一个更广泛的问题。

标签: laravel phpunit


【解决方案1】:

更改:
use PHPUnit\Framework\TestCase;
至:
use Tests\TestCase;

为什么?

当您的 ExampleTest 扩展 PHPUnit\Framework\TestCase Laravel 应用程序永远不会在测试中初始化,因此您无法访问 Laravel 功能,如工厂。

文档告诉您扩展PHPUnit\Framework\TestCase;,但它指的是单元测试。功能测试应该扩展Tests\TestCase。这是很新的东西。在 Laravel 5.8 之前,单元测试和功能测试都默认扩展 Tests\TestCase。我个人只是将所有测试定义为功能测试以避免此类问题。

【讨论】:

  • 我正在使用单元测试。即使扩展 PHPUnit\Framework\TestCase ,我也不能在数据提供者中使用工厂。
  • @JarsOfJam-Scheduler 我明白你现在的意思了。如果您在数据提供程序中调用$this-&gt;refreshApplication();,它将起作用。但是你仍然需要扩展Tests\TestCase
  • 这很有意义,因为您可以在框架之外进行纯单元测试,谢谢您的解释。
【解决方案2】:

问题是由于在使用工厂时使用了dataProvider。更准确地说:当 Laravel 工厂使用时,不应使用 PHPUnit 数据提供程序。

【讨论】:

  • 我想知道你应该如何将对象放入数据提供者中而不用手动输入它们。
【解决方案3】:

我认为你需要使用 WithFaker 特征来使用 faker :

<?php

namespace Tests\Unit;

use PHPUnit\Framework\TestCase;
use App\Models\Project;
use Illuminate\Foundation\Testing\WithFaker;

class ExampleTest extends TestCase
{
     use WithFaker;
     
     // ...
 }

【讨论】:

  • 它不起作用,同样的问题 :) 我将尝试从 Laravel 扩展。 (使用 Illuminate\Foundation\Testing\TestCase; )
  • 编辑:Illuminate\Foundation\Testing\TestCase 让我实现了一个抽象方法。这绝对不同于我在官方文档中读到的(OP中给出的链接)
  • 顺便说一句 laravel.com/docs/8.x/database-testing#writing-factories 说不需要使用 WithFaker
猜你喜欢
  • 2021-11-29
  • 2020-03-24
  • 2016-06-04
  • 2018-11-23
  • 2013-07-17
  • 2017-11-16
  • 2021-02-02
  • 2016-05-21
  • 2016-05-16
相关资源
最近更新 更多