0

我无法为我正在处理的一段代码编写测试。我有两个表,我正在尝试为其创建一个联结表,如下所示:

CREATE TABLE charges (
    id bigint PRIMARY KEY,
    amount float,
    some_data hstore
)

CREATE TABLE shipments (
    id bigint PRIMARY KEY,
    weight float,
    some_data hstore
)

CREATE TABLE distributed_details (
    charges_id bigint references charges (id),
    shipments_id biging references shipments (id),
    amount float,
    another_calculated_field varchar
)

根据some_data字段中的某些标准,我必须提取一组费用和一组货物,charges.amount并按shipments.weight. 结果将被存储distributed_details。在进行此分配时,我还必须根据 中的剩余内容执行一些其他计算,some_data这些内容将存储在distributed_details.another_calculated_field.

class Distributor
{
    public $detailMapper;

    public function distribute($charges, $shipments)
    {
        foreach ($charges as $charge) {
            $distributedAmounts = $this->calculateDistributedAmounts($charge->getAmount(), $shipments);
            foreach ($shipments as $shipment) {
                $distributed_detail = $this->buildDistributedDetail($charge, $shipment, array_shift($distributedAmounts));
                $this->detailMapper->save($distributed_detail);
            }
        }
    }

    public function calculateDistributedAmounts($shipments) {}
    public function buildDistributedDetail($charge, $shipment, $distributedAmount) {}
}

是否有一种测试此功能的好方法,并确保这些分配的金额实际被提取并分配给每条记录?出于内存限制的原因,我已将每个细节的持久性委托给此方法中的 detailMapper - 我有时必须提取数万个货物,并且将所有产生的费用返回到一个数组中会使我的内存不足。

4

2 回答 2

1

没有完整的答案是不可能的。我的偏好始终是让测试用例安全地在生产环境中运行,这意味着它们不会永久地向数据库提交任何内容。虽然我在 Perl 中完成了大部分工作,但相同的测试方法应该能够适用于 PHP。

  1. 将您的数据库连接抽象为一个为您处理事务的类。

  2. 不要在重要的地方使用自动提交,或者确保它被正确封装。

  3. 创建一个可以替代真实连接的测试包装类。这与您的数据库连接具有所有相同的功能,并且它避免了自动提交等。不同之处在于 $database->commit() 是一个 noop,因此您的应用程序只认为它正在提交对数据库的更改。

这允许您为包括数据库查询在内的整个逻辑编写测试用例,而不会冒测试数据污染生产环境的风险。

于 2013-11-26T06:07:20.620 回答
0

有点晚了,但我最终为这个问题开发了一个合适的解决方案。这里有两个大问题:

  1. 表现。将数以万计的记录拉入内存并不是处理此过程的可行方法。
  2. 可测试性。

该解决方案也由多个部分组成:

  1. 不要将所有货物加载到内存中。在我的特定场景中,我使用Traversable PDO 语句逐个遍历结果。需要注意的是,它必须第二次重新运行查询,但可能还有其他方法可以重置不涉及执行此操作的指针。
  2. 将构建每个联结记录所需的计算与提取它们所需的过程分开。通过使用类似于Martin Fowler 的数量模式的实现遍历货物并分配数量,我们也可以单独测试该步骤。
  3. 最后,将记录分开保存到您选择的持久性模式(数据映射器、网关等)。使用最后一块,您可以包装所有内容并在需要时对其进行集成测试。

我在这里没有实际的例子,但这是一般的想法。

于 2016-04-11T18:04:45.573 回答