【问题标题】:Failing test that record saves to pivot table in laravel记录保存到laravel中的数据透视表的测试失败
【发布时间】:2018-12-22 04:07:21
【问题描述】:

我有一个 Board 模型和一个 Pin 模型,它们是多对多的。我正在测试以确保当创建一个引脚并分配一个板时,它会保存到数据透视表中。由于我是测试新手,所以我无法弄清楚这一点。

这是我的测试:

/** @test */
public function a_pin_can_belong_to_a_board()
{
    $board = create('App\Board');
    $pin = make('App\Pin');

    $response = $this->post('/pins/create', $pin->toArray());

    $pin->boards()->sync($board);

    $this->assertDatabaseHas('board_pin', [
        'board_id' => $board->id,
        'pin_id' => $pin->id
    ]);
}

这是我的错误:

1) Tests\Unit\PinTest::a_pin_can_belong_to_a_board
Illuminate\Database\QueryException: SQLSTATE[23000]: Integrity 
constraint violation: 19 NOT NULL constraint failed: board_pin.pin_id 
(SQL: insert into "board_pin" ("board_id", "pin_id") values (1, ))

Caused by
PDOException: SQLSTATE[23000]: Integrity constraint violation: 19 NOT 
NULL constraint failed: board_pin.pin_id

这是我的控制器:

public function store(Request $request)
{
    $this->validate($request, [
        'title' => 'required|max:200',
        'link' => 'required|max:255'
    ]);

    $pin = new Pin();

    $pin->title = $request->title;
    $pin->link = $request->link;
    $pin->user_id = auth()->id();

    $pin->save();

    $pin->boards()->sync($request->boards);

    return redirect("/pins/{$pin->id}");
}

任何帮助将不胜感激!谢谢!

【问题讨论】:

  • 图钉是否被保存?您可以从该 SQL 输出中看出 values 数组只有一个用于 board_id。值 (1, )) 部分。
  • 我对测试有点陌生,我该怎么说?当它被发布到该路线时,它不会被保存吗?

标签: php laravel testing eloquent phpunit


【解决方案1】:

您应该小心使用sync。我建议不要使用它,而是选择attach。原因如下:

你也可以使用sync方法来构造many-to-many 协会。 sync 方法接受一个 ID 数组放置在 中间表。任何不在给定数组中的 ID 都将是 从中间表中删除。所以,在这个操作之后 完整,只有给定数组中的 ID 将存在于 中间表

Documentation 请参阅“同步关联”。

$pin->boards()->attach([$board->id])

或者,虽然我不确定你为什么会选择这条路线,但你可以使用syncWithoutDetaching,它可以满足人们的期望:

如果您不想分离现有的 ID,您可以使用 syncWithoutDetaching 方法

主要问题似乎是您在pin 上使用了make,但是您没有保存它。您还通过发布到该端点来创建实例,但它与您在本地创建的实例不同。在您的情况下,$pin 没有 ID,因为它从未保存过。当您执行以下操作时,会使用相同的属性创建一个单独的 pin

$this->post('/pins/create', $pin->toArray());

如果您的回复包含 pin 的 id,您可以执行以下操作:

$pin_id = $response->getContent()->id;
$pin = Pin::find($pin_id);
$pin->boards()->attach([$board->id]);

【讨论】:

    【解决方案2】:

    这就是答案!我不只是在 pin 实例上使用 make 方法,而是使用 create 方法并将其持久化到数据库中,然后删除了 post 操作。见下文:

    /** @test */
    public function a_pin_can_belong_to_a_board()
    {
        $board = create('App\Board');
        $pin = create('App\Pin');
    
        $pin->boards()->sync($board);
    
        $this->assertDatabaseHas('board_pin', [
            'board_id' => $board->id,
            'pin_id' => $pin->id
        ]);
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-03-20
      • 2016-05-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多