2 回答

TA貢獻1942條經驗 獲得超3個贊
創建工廠并 100% 測試該工廠。
據我了解,您的Crate班級既是實體又是工廠。Crate::getDetails您可以通過將此創建責任轉移到工廠來進行重構。
這樣,您就可以僅使用“Given, When, Then”結構對創建邏輯進行單元測試。查看這篇關于干凈測試的帖子并導航到“測試應該簡潔且有意義”。
擁有這種結構將幫助您分辨輸入和輸出是什么。例如:
CrateDetailsFactoryTest.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貢獻2021條經驗 獲得超8個贊
使用上面的類,要正確地對其進行單元測試,您必須使用 DI 注入\Details::class其中一個getDetails()或 __constructor。然后為每個類的每個方法編寫測試,模擬任何類依賴項/屬性
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 中,您可以使用 dataprovider 將一組值作為單獨的測試傳遞給一個測試方法。 PHPUnit Docs - 數據提供者
您還可以為 \Details::class 編寫單獨的單元測試,斷言傳遞給 \Details::setItem1($item) 的內容實際上是在 item1 屬性上設置的。IE。
測試 \Details::class -
//test2
public function test() {
$details = new Details('some stuff');
$details->setItem1('expected');
self::assertSame('expected', $details->item1);
}
- 2 回答
- 0 關注
- 102 瀏覽
添加回答
舉報