jeroenvanrensen's avatar

PHPunit - Testing a BelongsToMany relationship in a unit test

Hi everyone,

I'm creating a blog with Laravel and I'm making the tag system. I'm using PHPunit for TDD, because I really like it. I was wondering: How could I test a BelongsToMany relationship in a unit test?

Here's the part of the test I'm currently having:

/** @test */
public function a_tag_has_posts()
{
    $this->withoutExceptionHandling();

    $tag = factory('App\Tag')->create();

    $post = factory('App\Post')->create();
}

How could I test that a post has multiple tags and a tags has multiple posts.

Thank you! Jeroen

If you need more information, please ask me

0 likes
5 replies
Thibaultvanc's avatar
Level 37

assuming you have a tags method on the Post::class

$post = factory(Post::class)->create();
$tag = factory(Tag::class)->create();


$this->assertCount(0,$post->fresh()->tags);

$post->tags()->attach($tag);

$this->assertTrue($post->tags()->first()->is($tag));
$this->assertCount(1,$post->fresh()->tags);
jeroenvanrensen's avatar

Hi @thibaultvanc,

Thanks for your answer. I've created this test, but I'm still having a problem: BadMethodCallException: Method Illuminate\Database\Eloquent\Collection::attach does not exist.

/** @test */
public function a_tag_has_posts()
{
    $this->withoutExceptionHandling();

    $tag = factory('App\Tag')->create();
    $post = factory('App\Post')->create();

    $this->assertCount(0, $tag->posts);

    $tag->posts->attach($post);

    $this->assertCount(1, $tag->fresh()->posts);
    $this->assertTrue($tag->posts()->first()->is($post));
}

I don't have an attach-method on my Tag model, but I do have this relationship:

public function posts()
{
    return $this->belongsToMany(Post::class, 'posts_tags');
}

So, do I have to make an attach function or should it be working?

Thank you! Jeroen

ElhamRasekh's avatar

@jeroenvanrensen when you write $tag->posts it just access to a magic property which produced by posts() method in tag model. it is just a property. if you want to attach something to it, you should use relation method. not property. so, it's correct to use $tag->posts()->doSomeThing....

Please or to participate in this conversation.