It is a very open question, i have been in the same place like you. I feel the best approach is to create helpers and structure your data according. Testing mainly consist of 3 steps, called arrange, act and assert.
Let's first focus on arrange, this is about creating your data. Create helpers for it, so you don't have to repeat your self. Multiple object returns is what i use, to avoid calling to many helpers.
public function createRoom(array $roomData)
{
$room = factory(Room::class)->create($roomData);
$ratePlans = factory(RatePlan::class, 3)->create(['room_id' => $room->id]);
$promotions = factory(Promotion:class, 3)->create();
$room->promotions()->saveMany($promotions);
return [$room, $ratePlans, $promotions];
}
As the scope of this task is very vague, it is just to show ideas. This can then easy be utilized in your test.
public testRoomCreate()
{
[$room, $ratePlans, $promotions] = $this->createRoom();
}
The act part of a test, calling the application is straight forward. Use Laravels inbuilt methods for this, which are implemented in the Laravel testcase.
For assertion, a good approach is to again create standardized methods to help you in your process.
public function assertRoomResponse($response, Room $room)
{
$response->assertJsonStructure(
[
'id',
'type',
]
);
$response->assertJson(
[
'id' => $room->id,
'type' => $room->type,
]
);
}
public function assertRoomDatabaseHas(Room $room)
{
$this->assertDatabaseHas('rooms', [
'type' => $room->type,
]);
}
There probably needs to be more logic related to relations etc. but if this is implemented you probably will have more assertions than most applications. This will make you able to write tests, that are fairly straightforward as shown below, but will require some maintenance to keep em generic. This thou solve your main problem of having trouble writing many tests.
public testRoomCreateWithTypeDouble()
{
[$room, $ratePlans, $promotions] = $this->createRoom(
[
'type' => 'double',
]
);
$response = $this->call('POST', 'api/room', [
'type' => $room->type,
]);
$this->assertRoomResponse($response, $room);
$this->assertRoomDatabaseHas($room);
}