PHP / Laravel: почему эта функция вызывается? - PullRequest
0 голосов
/ 14 ноября 2018

Я хотел бы понять, почему эта функция вызывается дважды в laravel, у меня есть эта Фабрика, определенная:

<?php

use Faker\Generator as Faker;

function my_callback (Faker $faker) { // <= LINE 5 
    return [
        // some key-value pairs, don't focus on that
        'id_ubicacion' => 1,
        'nombre' => $faker->name,
        'clase' => 'CONTROL ADMINISTRATIVO',
        'codigo' => $faker->ean13,
        // some other key-value pairs
    ];
} // <= LINE 29

$factory->define(App\Bien::class, 'my_callback');

тогда у меня есть следующие тесты:

<?php

namespace Tests\Unit;

use Tests\TestCase;
use Illuminate\Foundation\Testing\WithFaker;
use Illuminate\Foundation\Testing\RefreshDatabase;

use Faker\Factory as Faker;

class BienTest extends TestCase
{
    use RefreshDatabase;

    public function test__actualizar()
    {
        // setup
        $registro_a_actualizar = factory('App\Bien')->create(['id' => 1]);

        // more code...

    }

    public function test__destruir()
    {
        // setup
        $registro_a_destruir = factory('App\Bien')->create(['id' => 1]);

        // some code...
    }

когда я выполню PHPUnit я получаю следующую ошибку

Fatal error: Cannot redeclare my_callback() 

(previously declared in \inven\database\factories\FactoryBien.php:5) 

in \inven\database\factories\FactoryBien.php on line 29

спасибо, если вы можете мне объяснить: почему функция my_callback() вызывается более одного раза?

1 Ответ

0 голосов
/ 15 ноября 2018

Во-первых, мы должны понять, как работает тестовый бегун.

Даже если каждый тест выполняется в случайном порядке, это не совсем так. Кроме того, вы должны понимать, что setUp и tearDown всегда запускаются до и после каждого теста.

В методе setUp в Laravel оно обновит приложение, если оно не запущено:

if (! $this->app) {
    $this->refreshApplication();
}

Так что мы можем подумать, эй, у нас запущен один экземпляр приложения, поэтому нам больше не нужно ModelFactory, верно?

НЕВЕРНО .

В методе tearDown, который вызывается после каждого теста, он фактически уничтожает приложение непосредственно перед окончанием метода:

if ($this->app) {
    foreach ($this->beforeApplicationDestroyedCallbacks as $callback) {
        call_user_func($callback);
    }

    $this->app->flush();
    $this->app = null;
}

Это означает, что ваш файл ModelFactory включается при каждом запуске теста. Но это происходит в том же процессе PHP. Вот почему вы получаете ошибку уже определенной функции.

Чтобы доказать это легко, просто напишите это в своем файле ModelFactory:

global $a;
if (is_null($a)) {
    $a = 0;
}
else {
    $a++;
}
var_dump($a);

Вы увидите, что $a будет увеличиваться при каждом запуске теста.

Чтобы решить вашу проблему, вы должны просто использовать анонимные функции примерно так:

$factory->define(App\Bien::class, function (Faker $faker) {
    return [
        // some key-value pairs, don't focus on that
        'id_ubicacion' => 1,
        'nombre' => $faker->name,
        'clase' => 'CONTROL ADMINISTRATIVO',
        'codigo' => $faker->ean13,
        // some other key-value pairs
    ];
});
...