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

Php 记录保存到laravel中透视表的测试失败,php,laravel,testing,eloquent,phpunit,Php,Laravel,Testing,Eloquent,Phpunit,我有一个板模型和一个引脚模型,它们是多对多的。我正在测试,以确保在创建管脚并为其分配板时,它会保存到数据透视表中。我很难弄明白这一点,因为我是测试新手 这是我的测试: /** @test */ public function a_pin_can_belong_to_a_board() { $board = create('App\Board'); $pin = make('App\Pin'); $response = $this->post('/pins/crea

我有一个板模型和一个引脚模型,它们是多对多的。我正在测试,以确保在创建管脚并为其分配板时,它会保存到数据透视表中。我很难弄明白这一点,因为我是测试新手

这是我的测试:

/** @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}");
}

任何帮助都将不胜感激!谢谢大家!

答案就在这里!我没有在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
    ]);
}

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

您还可以使用sync方法构造多对多 协会。sync方法接受要放置在 中间表。不在给定数组中的任何ID都将被删除 从中间表中删除。那么这个手术之后呢, 完成后,只有给定数组中的ID将存在于 中间表

请参阅“同步关联”

或者,尽管我不确定您为什么会选择此路线,但您可以使用
syncWithoutDetaching
,这符合预期:

如果不想分离现有ID,可以使用 同步不分离法

主要问题似乎是您在
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]);

密码被保存了吗?从SQL输出中可以看出,值数组只有一个用于board_id。值(1,)部分。我对测试有些陌生,我该如何判断?当它被发送到那条路线时,它不会被保存吗?
$pin_id = $response->getContent()->id;
$pin = Pin::find($pin_id);
$pin->boards()->attach([$board->id]);