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

标签 php laravel testing automated-tests

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

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

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

最有效的方法是什么?

最佳答案

这是一个非常开放的问题,我和你一样处于同一个地方。我认为最好的方法是创建助手并根据其构建数据。测试主要分为3个步骤,分别是arrange、act和assert。

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

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

测试的实际部分,调用应用程序是很简单的。为此,请使用 Laravel 内置方法,这些方法在 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);
}

关于php - 如何在 Laravel 中高效地编写复杂业务逻辑的单元测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62713678/

相关文章:

php - 将 PHPUnit 与 Selenium 结合使用,如何测试元素是否包含某些内容?

php - 检查字符串是否至少有 75% 是大写

php - 仅允许1行时删除最后插入的行SQL

PHP将html字符串分割成一个数组,以标签的类名作为键

php - Laravel 5.4 升级后的 BroadcastServiceProvider.php 和 Broadcaster.php 问题

c++ - 如何使用 CMake 对库的私有(private)特性 (TDD) 进行单元测试

javascript - onChange 时自动提交选择

javascript - 使用 AJAX post 将对象数组发送到服务器端

php - Laravel - 如何从 Controller 设置 HTTP 响应状态代码

php - 在 mysqli 库中伪造错误条件