如何在 Laravel 中为复杂的业务逻辑高效编写单元测试



我正在编写一个房间预订引擎。计算有 3 层:房价计划、促销、预订查询(客户发送的请求信息(。

当客户发送预订查询时,包含预订日期,入住日期,退房日期,人数等信息,此请求将通过从价格计划和促销计算的多层逻辑传递以给出结果(是否可用,价格是多少..等(。

我确实为逻辑中的小计算部分编写了单元测试。但是,我需要编写一个集成测试,或一套集成测试,其中包含数百个特定输入数据和特定预期输出数据(不是工厂生成的随机数据(的测试用例。我的实体内部有很多关系,例如$room>费率计划,$ratePlan->促销......等等等等。编写一个测试用例已经足够累了,更不用说数百个了。

最有效的方法是什么?

这是一个非常开放的问题,我和你一样在同一个地方。我觉得最好的方法是创建助手并据此构建数据。测试主要包括 3 个步骤,分别称为安排、行动和断言。

让我们首先关注排列,这是关于创建您的数据。为它创建助手,这样你就不必重复你自己。我使用多个对象返回,以避免调用许多帮助程序。

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];
}

由于这项任务的范围非常模糊,它只是为了展示想法。然后,这可以很容易地在您的测试中使用。

public testRoomCreate()
{
[$room, $ratePlans, $promotions] = $this->createRoom();
}

测试的行为部分,调用应用程序是直接的。为此使用Laravels内置方法,这些方法在Laravel测试用例中实现。

对于断言,一个好方法是再次创建标准化方法来帮助您完成流程。

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,
]);
}

可能需要更多与关系等相关的逻辑,但如果实现了这一点,您可能会比大多数应用程序拥有更多的断言。这将使你能够编写测试,这些测试相当简单,如下所示,但需要一些维护才能保持通用性。这解决了您在编写许多测试时遇到问题的主要问题。

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);
}

最新更新