@laracoft But a trait is useless on its own. A trait is used inside classes. You can’t instantiate a trait by itself, so it’s difficult to test its methods without using horrible workarounds like reflection.
Traits are also usually used to augment functionality in some other class, so even if you did use something like reflection to execute a method in a trait, that method is probably going to be relying on other properties or methods, particularly methods you add into Eloquent model classes.
Consider a Publishable trait that has a couple of methods like this:
trait Publishable
{
public function publish(): bool
{
return $this->forceFill([
'published_at' => Date::now(),
])->save();
}
public function isPublished(): bool
{
return $this->is_published && $this->is_published->isPast();
}
}
This trait is useless on its own because it’s relying on the class it being used in to have a fluent forceFill method and a save method, and a published_at property, none of which exist in the trait itself. So if you use reflection to invoke the method, you’d then have to use some form of mocking or something for those methods and properties, in which case, what are you actually testing about the trait itself? Answer: extremely little. You’re not testing any actual behaviour.
So, this is why I prefer to test the trait’s functionality inside a class that actually uses the trait:
public function test_post_can_be_published(): void
{
$post = Post::factory()->unpublished()->create();
$this->assertFalse($post->isPublished());
$post->publish();
$this->assertTrue($post->fresh()->isPublished());
}