工厂在测试中计数 2 个模型而不是 1 个

Posted

技术标签:

【中文标题】工厂在测试中计数 2 个模型而不是 1 个【英文标题】:Factory counts 2 models instead of 1 in tests 【发布时间】:2020-04-27 10:10:34 【问题描述】:

我有这些迁移:

class CreateOrdersTable extends Migration

    public function up()
    
        Schema::create('orders', function (Blueprint $table) 
            $table->bigIncrements('id');
            $table->unsignedBigInteger('user_id');
            $table->timestamps();

            $table->foreign('user_id')->references('id')->on('users');
        );
    

class CreatePaymentsTable extends Migration

    public function up()
    
        Schema::create('payments', function (Blueprint $table) 
            $table->bigIncrements('id');
            $table->unsignedBigInteger('order_id');
            $table->timestamps();

            $table->foreign('order_id')->references('id')->on('orders');
        );
    


还有这些工厂:

$factory->define(Payment::class, function (Faker $faker) 
    return [
        'order_id' => factory(Order::class)->create(),
    ];
);
$factory->define(Order::class, function (Faker $faker) 
    return [
        'user_id' => factory(User::class)->create(),
    ];
);

现在在我的测试中我有这个:

/** @test */
public function it_should_count_1_order()

     $order = factory(Order::class)->create();

     $payment = factory(Payment::class)->create([
         'order_id' => $order->id,
     ]);

     $this->assertEquals(1, Order::count())

订单表计数给了我2。为什么?它应该是1,因为我告诉支付工厂用给定的订单覆盖order_id。我错过了什么吗?

【问题讨论】:

【参考方案1】:

你应该尝试像这样定义你的工厂:

$factory->define(Order::class, function (Faker $faker) 
    return [
        'user_id' => factory(User::class),
);

如果没有帮助,请确保在测试中使用 DatabaseTransactionsDatabseMigrations 测试,并在第一次运行测试之前清除数据库。否则每次运行测试时,您都会在数据库中获得越来越多的记录。

就个人而言,我认为使用这样的断言:

$this->assertEquals(1, Order::count())

在测试中不是一个好主意。当您创建更高级的测试时,您可能会决定创建一些其他附加数据,并且您不应该关心之前创建的模型。我个人希望这样的测试:

$initialOrdersCount = Order::count();

// here you run some actions you want to test

$this->assertSame($initialOrdersCount  + 1, Order::count());

这样,如果应用程序中发生任何其他事情或将被添加到测试中,我不在乎我是否在数据库 2 或 3 模型中。对我来说,数量或订单应该增加一是很重要的。

【讨论】:

【参考方案2】:

由于您的Payment factory 正在创建Order,因此您无需在之前创建Order 并将其传递给Payment factory

/** @test */
public function it_should_count_1_order()

     $payment = factory(Payment::class)->create();

     $this->assertEquals(1, Order::count())

【讨论】:

这不能回答我的问题。我仍在覆盖 order_id。为什么它创建 2 个订单而不是 1 个? 无论你在 php 中做什么,如果你在数组中定义了一些东西,它必须在某个时候解析:)

以上是关于工厂在测试中计数 2 个模型而不是 1 个的主要内容,如果未能解决你的问题,请参考以下文章

为啥我的 Django 工厂函数在本地数据库中创建模型,而不是测试数据库?

等待2个方法而不是1个[重复]

在 spark 1.6 中计数(不同)不能与 hivecontext 查询一起使用

在 PySpark Dataframe 中计数零次出现

在 hive mapreduce 中计数 desc

在访问报告中计数