很多时候,开发人员尝试测试 100%(或几乎 100%)的代码。显然,这是每个团队应该为他们的项目达到的目标,但从我的角度来看,只应该完全测试整个代码的一部分:您的域。
域基本上是代码中定义项目实际功能的部分。例如,当您将实体持久保存到数据库时,您的域不负责将其持久保存在数据库上,而是确保持久数据根据您的业务模型有意义。可能,当您将数据保存到数据库时,您将使用 PHP Doctrine 等外部库。该库已经经过充分测试,无需测试它的功能。如果您将正确的数据传递给学说,它将毫无问题地保存到数据库中。
以下部分中显示的示例并不试图展示领域驱动设计是如何工作的,有很多文章对其进行了很好的解释。我将尝试展示如何明确定义和解耦您的域可以帮助轻松测试并专注于您的应用程序的功能。
该示例是在 Symfony 环境上构建并使用 PHPUnit 库的,但这个想法对任何语言或框架都有效。
假设我们的应用程序连接到一个外部 API,该 API 返回有关指定日期的下雨概率的数据。返回的数据如下所示:
{ "date" : "2022-12-01", "rain_probability" : 0.75 }
现在,我们必须获取这些数据并按照以下映射对其进行分类:
并将结果保存在由以下实体描述的数据库表中:
#[ORM\Entity(repositoryClass: RainMeasure::class)] class RainMeasure { #[ORM\Column] private string $date; #[ORM\Column] private float $probability; #[ORM\Column(length: 10)] private string $label; // Getters and setters // ....... }
让我们创建一个处理程序,它获取外部 api 数据,根据下雨概率设置标签并将其保存到数据库。
class RainMeassureHandler { private EntityManagerInterface $em; public function __construct(EntityManagerInterface $em) { $this->em = $em; } public function saveMeasure(array $measureData): void { if($measureData['rain_probability'] = 0.40 && $measureData['rain_probability'] setDate($measureData['date']); $rainMeasure->setProbability($measureData['rain_probability']); $rainMeasure->setLabel($label); $this->em->persist($rainMeasure); $this->em->flush(); } }
如果我们尝试为上述处理程序创建一个测试,我们会发现我们需要注入EntityManagerInterface,因为我们想要测试的行为(根据概率值设置标签)是耦合在同一个处理程序中,将结果保存到数据库中。我们可以尝试使用模拟和存根加载 EntityManagerInterface,但是有必要吗?显然不是。正如之前所说,我们应该尝试专注于测试属于我们领域的行为,即根据下雨概率获得正确的标签。
为了简化我们的测试,我们将要测试的行为移至另一个类:
class RainMeasureLabelHandler { public function getLabelFromProbability(float $prob): string { if($prob = 0.40 && $prob现在,我们的 RainMeassureHandler 将如下所示:
class RainMeasureHandler { private EntityManagerInterface $em; public function __construct(EntityManagerInterface $em) { $this->em = $em; } public function saveMeasure(array $measureData): void { $rainMeasureLabelHandler = new RainMeasureLabelHandler(); $label = $rainMeasureLabelHandler->getLabelFromProbability($measureData['rain_probability']); $rainMeasure = new RainMeasure(); $rainMeasure->setDate($measureData['date']); $rainMeasure->setProbability($measureData['rain_probability']); $rainMeasure->setLabel($label); $this->em->persist($rainMeasure); $this->em->flush(); } }现在我们可以专注于测试我们的RainMeasureLabelHandler,它将成为我们域的一部分,并且不依赖于外部层。测试它很简单,如图所示:
结论
我想说其他类型的测试也很有用。也许我们有一个 api,并且希望使用一个测试环境来测试输入和输出,其中包括数据库和我们可能需要的其他资源。但是,请记住将您的域解耦并进行全面测试。
免责声明: 提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发到邮箱:[email protected] 我们会第一时间内为您处理。
Copyright© 2022 湘ICP备2022001581号-3