代码之家  ›  专栏  ›  技术社区  ›  L. Fox

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

  •  0
  • L. Fox  · 技术社区  · 8 年前

    我有一个板模型和一个销模型,它们是多对多的。我正在测试以确保在创建和分配一个板时,它会保存到透视表中。因为我刚开始测试,所以我很难弄清楚这一点。

    这是我的测试:

    /** @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 回复  |  直到 8 年前
        1
  •  0
  •   L. Fox    8 年前

    答案在这里!我没有在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
        ]);
    }
    
        2
  •  0
  •   Alex Harris    8 年前

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

    也可以使用同步方法构造多对多 协会。sync方法接受要放置在 中间桌。任何不在给定数组中的ID都将 从中间桌上取下。所以这次手术后 完成,只有给定数组中的ID将存在于 中间桌

    Documentation 请参见“同步关联”。

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

    或者,尽管我不知道你为什么选择这条路线 syncWithoutDetaching 这正是人们所期望的:

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

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

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

    如果您的响应包含PIN的ID,您可以执行如下操作:

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