This is an example code I'm using to test the states of our Booking model. It only tests the "business" logic that's returned by the state is correct, that way I know I can rely on those states in tests.
If someone on my team or I accidentally changes the state or data inside the booking factory, for example change the appointment date to be one in the past or just don't set it anymore, I know I'll get a failing test and clear reason why. It give's good confidence that I can use these in a known, unit tested state in all of my tests and only override the data as needed to test a specific scenario.
<?php
use Tests\TestCase;
use App\Member\Member;
use App\Booking\Booking;
use Illuminate\Foundation\Testing\DatabaseTransactions;
class BookingModelFactoryTest extends TestCase
{
use DatabaseTransactions;
public function test_default_state()
{
$booking = factory(Booking::class)->create();
$this->assertNotNull($booking->member);
$this->assertNotNull($booking->client);
$this->assertNotEquals($booking->client_id, $booking->member_id, 'The client and the member must be different.');
$this->assertTrue($booking->member->isPro(), 'The member must be a pro.');
$this->assertEquals(80, $booking->hourly_rate, 'The standard hourly rate must be used.');
$this->assertEquals(2, $booking->hours, 'The standard number of hours must be used.');
$this->assertNotNull($booking->appointment_at, 'Booking must have a date set.');
$this->assertTrue($booking->appointment_at->isFuture(), 'Booking must be for a future date.');
$this->assertEquals($booking->client->getKey(), $booking->created_by, 'Booking must be created/sent by the client.');
}
public function test_accepted_state()
{
$booking = factory(Booking::class)->states('accepted')->create();
$this->assertNotNull($booking->accepted_at);
$this->assertTrue($booking->accepted_at->isPast());
$this->assertEquals($booking->getOtherMember($booking->createdBy)->getKey(), $booking->accepted_by);
}
}