PHPUnit:如何对多个if-else/工厂进行单元测试?
我有一个类PHPUnit:如何对多个if-else/工厂进行单元测试?,php,unit-testing,phpunit,tdd,Php,Unit Testing,Phpunit,Tdd,我有一个类ParentIdResolver,它根据类型返回产品的父id。 该类看起来像: <?php namespace App\Model; use App\Model\Product\Bundle; use App\Model\Product\Configurable; use App\Model\Product\Downloadable; class ParentIdResolver { /** * @var Bundle */ privat
ParentIdResolver
,它根据类型返回产品的父id。该类看起来像:
<?php
namespace App\Model;
use App\Model\Product\Bundle;
use App\Model\Product\Configurable;
use App\Model\Product\Downloadable;
class ParentIdResolver
{
/**
* @var Bundle
*/
private $bundle;
/**
* @var Configurable
*/
private $configurable;
/**
* @var Downloadable
*/
private $downloadable;
public function __construct(
Bundle $bundle,
Configurable $configurable,
Downloadable $downloadable
) {
$this->bundle = $bundle;
$this->configurable = $configurable;
$this->downloadable = $downloadable;
}
public function getParentId($productId, $productType)
{
$parentIds = [];
if ($productType == 'bundle') {
$parentIds = $this->bundle->getParentIdsByChild($productId);
} elseif ($productType == 'configurable') {
$parentIds = $this->configurable->getParentIdsByChild($productId);
} elseif ($productType == 'downloadable') {
$parentIds = $this->downloadable->getParentIdsByChild($productId);
}
return $parentIds[0] ?? null;
}
}
我觉得我做得不对,也许我需要重构主类?请说明在这种情况下,您将如何重构或编写单元测试。有些人会称之为“问,不要说”。看起来像这样
<?php
namespace App\Model;
use App\Model\Product\ResolvesParentId;
class ParentIdResolver
{
/** @var ResolvesParentId[] */
private $parentIdResolvers;
public function __construct(array $parentIdResolvers)
{
$this->parentIdResolvers = $parentIdResolvers;
}
public function getParentId(int $productId, string $productType): int
{
foreach ($this->parentIdResolvers as $parentIdResolver) {
if ($parentIdResolver->supports($productType)) {
return $parentIdResolver->getParentId($productId)[0] ?? null;
}
}
return null;
}
}
如果测试成功并且代码正常工作,这将是一个更好的选择。@El_Vanja注意到了!您可以立即从测试和模拟中删除所有if
语句。测试将更加简洁way@PtrTon是的,这是重构单元测试的另一个选择。但是关于重构主类呢?你认为还有改进的余地吗?我给你留下了一个更详细的方法你是说“告诉,不要问”的TDA方法?现在我觉得一直出错很傻:)你会怎么使用它#用法?将包含捆绑包
、可配置
和可下载
实例的数组注入ParentIdResolver
。然后在该数组中查找正确的实现,并基于它解析父id
<?php
namespace App\Model;
use App\Model\Product\ResolvesParentId;
class ParentIdResolver
{
/** @var ResolvesParentId[] */
private $parentIdResolvers;
public function __construct(array $parentIdResolvers)
{
$this->parentIdResolvers = $parentIdResolvers;
}
public function getParentId(int $productId, string $productType): int
{
foreach ($this->parentIdResolvers as $parentIdResolver) {
if ($parentIdResolver->supports($productType)) {
return $parentIdResolver->getParentId($productId)[0] ?? null;
}
}
return null;
}
}
<?php
namespace App\Model\Product;
interface ResolvesParentId
{
public function supports(string $productType): bool;
public function getParentIdsByChild(int $productId): array;
}
<?php
namespace App\Model\Product;
class Bundle implements ResolvesParentId
{
public function supports(string $productType): bool
{
return $productType === 'bundle';
}
public function getParentIdsByChild(int $productId): array
{
// Your implementation here.
}
}
<?php
namespace App\Model\Product;
class Configurable implements ResolvesParentId
{
public function supports(string $productType): bool
{
return $productType === 'configurable';
}
public function getParentIdsByChild(int $productId): array
{
// Your implementation here.
}
}
<?php
namespace App\Model\Product;
class Downloadable implements ResolvesParentId
{
public function supports(string $productType): bool
{
return $productType === 'downloadable';
}
public function getParentIdsByChild(int $productId): array
{
// Your implementation here.
}
}