Upgrade to Pro — share decks privately, control downloads, hide ads and more …

モックの泥沼から脱却するために、あえてDBにつないでテストしている話

 モックの泥沼から脱却するために、あえてDBにつないでテストしている話

PHPerKaigi2021

Avatar for Kazuhei Arai

Kazuhei Arai

March 27, 2021
Tweet

More Decks by Kazuhei Arai

Other Decks in Programming

Transcript

  1. ς Ϋ ϊ ϩ δ ʔ ͷ ྗ Ͱ M

    & A ʹ ྲྀ ௨ ֵ ໋ Λ
  2. ϞοΫ͠ͳ͍Ϣχοτςετ class CommonTime { 
 public function __construct(int $timestamp) {

    $this->timestamp = $timestamp; } 
 public static function fromString($string) { return new static(strtotime($string)); } 
 public function getHour(): string { return date('H', $this->timestamp); }
  3. ϞοΫ͠ͳ͍Ϣχοτςετ public function testGetHour() { $time = CommonTime::fromString('2017-01-01 10:21:00'); $this->assertEquals('10',

    $time->getHour()); } จࣈྻ͔Β$PNNPO5JNFΫϥεΛ࡞ͬͯɺHFU)PVS͕࣌ؒ Λฦ͢͜ͱΛςετ
  4. ϞοΫΛ࢖ͬͨϢχοτςετ class MessageDomainService { 
 public function notifyMessage(MessageId $messageId): void

    { $message = $this->messageRepository->get($messageId); if ($message->needsNotification()) { $this->notificationRepository->add($message->notification()); } } ϝοηʔδΛऔಘͯ͠ɺඞཁͳΒ௨஌΋௥Ճ͢Δͱ͍͏Α͏ ͳॲཧ
  5. ϞοΫΛ࢖ͬͨϢχοτςετ public function testNotifyMessage() { $needsNotifyMessage = new Message(...); $this->mock(MessageRepository::class,

    function ($mock) use ($needsNotifyMessage) { $mock->shouldReceive('get') ->andReturn($needsNotifyMessage); }); $this->mock(NotificationRepository::class, function ($mock) use ($needsNotifyMessage) { $mock->shouldReceive('add') ->with($needsNotifyMessage->notification()); }); $domainService = app()->make(MessageDomainService::class); $domainService->notifyMessage($needsNotifyMessage->id()); } ҰͭҰͭͷσʔλΞΫηε෦෼ΛϞοΫʹͯ͠ɺؔ਺͕ݺ͹ Ε͍ͯΔ͔Ͳ͏͔Λ֬ೝ͍ͯ͘͠ɻ
  6. ϞοΫΛ࢖ͬͨϢχοτςετ public function testNotifyMessage() { $needsNotifyMessage = new Message(...); $this->mock(MessageRepository::class,

    function ($mock) use ($needsNotifyMessage) { $mock->shouldReceive('get') ->andReturn($needsNotifyMessage); }); $this->mock(NotificationRepository::class, function ($mock) use ($needsNotifyMessage) { $mock->shouldReceive('add') ->with($needsNotifyMessage->notification()); }); $domainService = app()->make(MessageDomainService::class); $domainService->notifyMessage($needsNotifyMessage->id()); } σʔλϕʔε͔Βऔಘͨ͠σʔλΛ࢖ͬͯɺෳ਺ͷςʔϒϧʹॻ͖ ࠐΈΛ͍ͯ͘͠Α͏ͳ৔߹ɺͨ͘͞ΜͷσʔλϕʔεΞΫηεΛ ϞοΫ͢Δඞཁ͕͋Δɻ
  7. ͋͑ͯɺ%#ʹͭͳ͙ public function testNotifyMessage() { $needsNotifyMessage = new Message(...); $domainService

    = app()->make(MessageDomainService::class); $domainService->notifyMessage($needsNotifyMessage->id());
 
 $notification = $this->notificationRepository->first(); $this->assertEquals($needsNotifyMessage->notification(), $notification) } ࣮ࡍͷ%#ʹॻ͖ࠐΜͰɺͦΕΛऔΓग़ͯ͠Ұக͍ͯ͠ Δ͔֬ೝ͢Δ͚ͩɻͱͯ΋γϯϓϧ
  8. ςετޙͷ෭࡞༻ΛͲ͏΍ͬͯରॲ͢Δ͔ αϯϓϧίʔυ͸-BSBWFMΛ࢖ͬͨ΋ͷɻTFUVQ ࣌ʹ USBOTBDUJPOΛுΓɺUFBS%PXO ࣌ʹSPMMCBDL͍ͯ͠Δ <?php declare(strict_types=1); namespace Tests; use

    Illuminate\Foundation\Testing\DatabaseTransactions; abstract class BaseDbIntegrationTest extends TestCase { use DatabaseTransactions; }
  9. ࣮ߦ࣌ؒΛͲ͏͢Δ͔ 1)16OJUͷઃఆͰςετΛ෼ׂ͠ɺ࣮ߦλΠϛϯάΛௐ੔͢ Δ͜ͱͰରॲ <testsuites> <testsuite name="Feature"> <directory suffix="Test.php">./tests/Feature</directory> </testsuite> <testsuite

    name="DbIntegration"> <directory suffix="Test.php">./tests/DbIntegration</directory> </testsuite> <testsuite name="Unit"> <directory suffix="Test.php">./tests/Unit</directory> </testsuite> </testsuites>