2 回答
TA贡献1876条经验 获得超6个赞
创建一个工厂并100%测试该工厂。
据我所知,您的 Crate 类既是实体又是工厂。您可以通过将此创建责任移动到工厂来重构。Crate::getDetails
这样,您只能通过使用“给定,何时,然后”结构对创建逻辑进行单元测试。查看这篇关于干净测试的文章,并导航到“测试应该简洁而有意义”。
拥有此结构将帮助您判断输入和输出是什么。例如:
板条箱详细信息工厂测试.php
class CrateDetailFactoryTest extends TestCase
{
public function testCreateCrateDetail(): void
{
// Given
$crate = $this->givenThereIsACrate();
$boxes = $this->givenThereAreTwoRedBoxes();
// When
$crateDetail = $this->crateDetailFactory->createCrateDetail(
$crate,
$boxes
);
// Then
// (Unnecessary instanceof, if you have strict return types)
self::assertInstanceOf(Detail::class, $crateDetail);
self::assertCount(2, $crateDetail->getBoxes());
self::assertEquals(
'red',
$crateDetail->getBoxes()->first()->getColor()
);
}
}
这样就可以覆盖您的创建逻辑;从这里,你可以简单地将你的工厂注入你需要的地方,在单元测试期间,你只需模拟它:
板条箱服务.php
class CrateServiceTest extends TestCase
{
private $crateDetailFactory;
private $crateService;
public function setUp(): void
{
$this->crateDetailFactory = $this->prophesize(CrateDetailFactory::class);
$this->crateService = new CrateService(
$this->crateDetailFactory->reveal()
);
}
public function testAMethodThatNeedsCrateDetails(): void
{
// Given
$crate = $this->givenIHaveACrateWithTwoBoxesInIt();
$boxes = $crate->getBoxes();
// When
$result = $this->crateService->AMethodThatNeedsCrateDetails();
// Then
$this->crateDetailFactory->createCrateDetail($crate, $boxes)
->shouldBeCalledOnce();
}
}
我希望这是有用的。干杯!:)
TA贡献1785条经验 获得超4个赞
使用上面的类,要正确进行单元测试,您必须使用DI注入其中一个或__constructor。然后为每个类的每个方法编写测试,模拟任何类依赖项/属性\Details::classgetDetails()
class Create
{
public function getDetails(\Details $details)
}
//test.php
$mockDetails = $this->createMock(\Details::class)
->expects($this-once())
->method('item1')
->with('some_arg')
->willReturn('xyz')
$mockBox = $this-createMock(\Box::class)
......
$crate = new Create($boxMock);
$result = $crate->item1($mockDetails);
$this-assertSame('xyz', $result);
如果对于一种方法来说,这感觉像是你的嘲笑方式,那么你应该考虑重构以使代码更具可测试性。
就多个项目的断言而言,在 PHPUnit 中,您可以使用数据提供器将值数组作为单独的测试传递给一个测试方法。PHPUnit Docs - Data Providers
您还将为 \Details::类编写单独的单元测试,该类断言传递给 \Details::setItem1($item) 的内容实际上是在 item1 属性上设置的。即。
测试 \详细信息::类 -
//test2
public function test() {
$details = new Details('some stuff');
$details->setItem1('expected');
self::assertSame('expected', $details->item1);
}
- 2 回答
- 0 关注
- 174 浏览
添加回答
举报
