Как стать автором
Обновить

Комментарии 10

НЛО прилетело и опубликовало эту надпись здесь
Попробуйте запись:
$faker->unique()->lexify('???')

НЛО прилетело и опубликовало эту надпись здесь
А в системе обязательно должен находиться список этих статусов?
Если они не так важны, то можно удалять их перед запуском каждого теста с помощью запроса внутри функции setUp().
Ещё есть удобные трейты — DatabaseTransactions и RefreshDatabase. Первый открывает транзакцию и не закрывает её, поэтому состояние базы не изменяется, а второй — делает artisan migrate:refresh перед каждым тестом и откатывает-накатывает состояние БД, но это не всегда применимо.

Возьми одно случайное значение из уже сохраненных в базу.

Зачем использовать func_get_arg(), если можно просто добавить аргумент array $attributes в саму фабрику?


И для того, чтобы связанные модели создавались не внутри фабрик, а во время фактического создания главной модели, можно просто не вызывать ->create():


return [
    'user_id' => factory(User::class),
];

Если в фабрику будет передан свой user_id, то дополнительный пользователь создан не будет.

Круто, попробую воспользоваться советом
А если просто исправить фабрик до такого состояния?
$factory->define(Order::class, function (Faker $faker) {
    return [
        'user_id' => function () {
            return factory(User::class)->create()->id;
        }
    ];
});

и причем тут TDD?
и почему «Хитрости», хотя в статье один только костыль?
Достаточно просто сделать вот так:
$factory->define(Order::class, function (Faker $faker) {
    return [
        'user_id' => function () {
                return factory(User::class)->create()->id;
        }
    ];
});


и будет ровно то, что хочет автор. Юзер создастся только тогда, когда мы не передадим юзер_айди явно.
Во-первых:

$factory->define(Order::class, function (Faker $faker, $passedArguments = []) {
    return [
        'user_id' => function () use ($passedArguments) {
            // Если не передали user_id, то создаём своего
            if (! array_key_exists('user_id', $passedArguments)) {
                return factory(User::class)->create()->id;
            }
        }
    ];
});

Даст идентичный результат

Во-вторых, что важнее:
Данной проблемы, которую вы описываете, не существует
Вот вам пример из реального проекта, тест написал специально для вас

<?php

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

use Faker\Generator as Faker;
use Illuminate\Support\Str;

$factory->define(\Constructor\Auth\Models\User::class, function (Faker $faker) {
    return [
        'name' => $faker->name,
        'email' => $faker->unique()->safeEmail,
        'password' => bcrypt('secret'),
        'remember_token' => Str::random(10),
        'guid' => $faker->unique()->uuid,
    ];
});

<?php

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

use Constructor\Auth\Models\User;
use Constructor\Calculations\Models\Calculation;
use Faker\Generator as Faker;

$factory->define(Calculation::class, function (Faker $faker) {

    $guid = $faker->unique()->uuid;

    return [
        'guid' => $guid,
        'name' => $faker->incrementalName('Демо рассчёт'),
        'user_guid' => function () {
            return factory(User::class)->create()->guid;
        },
        'is_actual' => true,
        'amount' => 0,
        'original_guid' => $guid,
        'previous_guid' => null,
        'next_guid' => null,
        'is_visible' => true,
        'is_changed' => false,
    ];
});


namespace Tests\Unit;

use Constructor\Auth\Models\User;
use Constructor\Calculations\Models\Calculation;
use Tests\TestCase;

class FactoryTest extends TestCase
{
    public function testCreateAddOneUser()
    {
        // Given user
        $user = factory(User::class)->create();
        // When we use Order factory and provide user_id parameter
        $calculation = factory(Calculation::class)->create(['user_guid' => $user->guid]);
        // Then we should have new Order::class instance with provided user_id
        $this->assertEquals($user->guid, $calculation->user_guid);
        // Let's check that system has one user in DB
        $this->assertEquals(1, User::count());
    }
}


$ phpunit -- tests/Unit/FactoryTest.php
> OK (1 test, 2 assertions)

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории