记录保存到laravel中的数据透视表的失败测试

时间:2018-07-13 18:16:42

标签: php laravel testing eloquent phpunit

我有一个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}");
}

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

2 个答案:

答案 0 :(得分:0)

这是答案!我不仅使用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
    ]);
}

答案 1 :(得分:0)

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

  

您还可以使用sync方法构造多对多   协会。 sync方法接受一组ID放置在   中间表。不在给定数组中的所有ID都将是   从中间表中删除。因此,此操作之后   完成后,只有给定数组中的ID将存在于   中间表

Documentation请参阅“同步关联”。

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

或者,尽管我不确定您为什么选择这条路线,但是您可以使用syncWithoutDetaching来达到预期效果:

  

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

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

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

如果您的响应中包含图钉的ID,则可以执行以下操作:

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