From 4b3ed2b7ba85a6db0ddce9b1a0174dedbc4d17ff Mon Sep 17 00:00:00 2001 From: Alejandro Celaya Date: Sat, 22 Oct 2022 14:16:42 +0200 Subject: [PATCH] Migrated LocateVisitsCommandTest to use PHPUnit mocks --- .../Command/Visit/LocateVisitsCommandTest.php | 99 +++++++++---------- 1 file changed, 44 insertions(+), 55 deletions(-) diff --git a/module/CLI/test/Command/Visit/LocateVisitsCommandTest.php b/module/CLI/test/Command/Visit/LocateVisitsCommandTest.php index 0db2f493..418e3af6 100644 --- a/module/CLI/test/Command/Visit/LocateVisitsCommandTest.php +++ b/module/CLI/test/Command/Visit/LocateVisitsCommandTest.php @@ -6,8 +6,6 @@ namespace ShlinkioTest\Shlink\CLI\Command\Visit; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; -use Prophecy\Argument; -use Prophecy\Prophecy\ObjectProphecy; use Shlinkio\Shlink\CLI\Command\Visit\DownloadGeoLiteDbCommand; use Shlinkio\Shlink\CLI\Command\Visit\LocateVisitsCommand; use Shlinkio\Shlink\CLI\Util\ExitCodes; @@ -36,28 +34,21 @@ class LocateVisitsCommandTest extends TestCase use CliTestUtilsTrait; private CommandTester $commandTester; - private ObjectProphecy $visitService; - private ObjectProphecy $visitToLocation; - private ObjectProphecy $lock; + private MockObject $visitService; + private MockObject $visitToLocation; + private MockObject $lock; private MockObject $downloadDbCommand; protected function setUp(): void { - $this->visitService = $this->prophesize(VisitLocator::class); - $this->visitToLocation = $this->prophesize(VisitToLocationHelperInterface::class); + $this->visitService = $this->createMock(VisitLocator::class); + $this->visitToLocation = $this->createMock(VisitToLocationHelperInterface::class); - $locker = $this->prophesize(Lock\LockFactory::class); - $this->lock = $this->prophesize(Lock\LockInterface::class); - $this->lock->acquire(false)->willReturn(true); - $this->lock->release()->will(function (): void { - }); - $locker->createLock(Argument::type('string'), 600.0, false)->willReturn($this->lock->reveal()); + $locker = $this->createMock(Lock\LockFactory::class); + $this->lock = $this->createMock(Lock\LockInterface::class); + $locker->method('createLock')->with($this->isType('string'), 600.0, false)->willReturn($this->lock); - $command = new LocateVisitsCommand( - $this->visitService->reveal(), - $this->visitToLocation->reveal(), - $locker->reveal(), - ); + $command = new LocateVisitsCommand($this->visitService, $this->visitToLocation, $locker); $this->downloadDbCommand = $this->createCommandMock(DownloadGeoLiteDbCommand::NAME); $this->commandTester = $this->testerForCommand($command, $this->downloadDbCommand); @@ -78,14 +69,22 @@ class LocateVisitsCommandTest extends TestCase $location = VisitLocation::fromGeolocation(Location::emptyInstance()); $mockMethodBehavior = $this->invokeHelperMethods($visit, $location); - $locateVisits = $this->visitService->locateUnlocatedVisits(Argument::cetera())->will($mockMethodBehavior); - $locateEmptyVisits = $this->visitService->locateVisitsWithEmptyLocation(Argument::cetera())->will( - $mockMethodBehavior, - ); - $locateAllVisits = $this->visitService->locateAllVisits(Argument::cetera())->will($mockMethodBehavior); - $resolveIpLocation = $this->visitToLocation->resolveVisitLocation(Argument::any())->willReturn( - Location::emptyInstance(), - ); + $this->lock->method('acquire')->with($this->isFalse())->willReturn(true); + $this->visitService->expects($this->exactly($expectedUnlocatedCalls)) + ->method('locateUnlocatedVisits') + ->withAnyParameters() + ->willReturnCallback($mockMethodBehavior); + $this->visitService->expects($this->exactly($expectedEmptyCalls)) + ->method('locateVisitsWithEmptyLocation') + ->withAnyParameters() + ->willReturnCallback($mockMethodBehavior); + $this->visitService->expects($this->exactly($expectedAllCalls)) + ->method('locateAllVisits') + ->withAnyParameters() + ->willReturnCallback($mockMethodBehavior); + $this->visitToLocation->expects( + $this->exactly($expectedUnlocatedCalls + $expectedEmptyCalls + $expectedAllCalls), + )->method('resolveVisitLocation')->withAnyParameters()->willReturn(Location::emptyInstance()); $this->downloadDbCommand->method('run')->withAnyParameters()->willReturn(ExitCodes::EXIT_SUCCESS); $this->commandTester->setInputs(['y']); @@ -98,12 +97,6 @@ class LocateVisitsCommandTest extends TestCase } else { self::assertStringNotContainsString('Continue at your own', $output); } - $locateVisits->shouldHaveBeenCalledTimes($expectedUnlocatedCalls); - $locateEmptyVisits->shouldHaveBeenCalledTimes($expectedEmptyCalls); - $locateAllVisits->shouldHaveBeenCalledTimes($expectedAllCalls); - $resolveIpLocation->shouldHaveBeenCalledTimes( - $expectedUnlocatedCalls + $expectedEmptyCalls + $expectedAllCalls, - ); } public function provideArgs(): iterable @@ -122,10 +115,12 @@ class LocateVisitsCommandTest extends TestCase $visit = Visit::forValidShortUrl(ShortUrl::createEmpty(), Visitor::emptyInstance()); $location = VisitLocation::fromGeolocation(Location::emptyInstance()); - $locateVisits = $this->visitService->locateUnlocatedVisits(Argument::cetera())->will( - $this->invokeHelperMethods($visit, $location), - ); - $resolveIpLocation = $this->visitToLocation->resolveVisitLocation(Argument::any())->willThrow($e); + $this->lock->method('acquire')->with($this->isFalse())->willReturn(true); + $this->visitService->expects($this->once()) + ->method('locateUnlocatedVisits') + ->withAnyParameters() + ->willReturnCallback($this->invokeHelperMethods($visit, $location)); + $this->visitToLocation->expects($this->once())->method('resolveVisitLocation')->willThrowException($e); $this->downloadDbCommand->method('run')->withAnyParameters()->willReturn(ExitCodes::EXIT_SUCCESS); $this->commandTester->execute([], ['verbosity' => OutputInterface::VERBOSITY_VERBOSE]); @@ -133,8 +128,6 @@ class LocateVisitsCommandTest extends TestCase $output = $this->commandTester->getDisplay(); self::assertStringContainsString('Processing IP', $output); self::assertStringContainsString($message, $output); - $locateVisits->shouldHaveBeenCalledOnce(); - $resolveIpLocation->shouldHaveBeenCalledOnce(); } public function provideIgnoredAddresses(): iterable @@ -149,10 +142,12 @@ class LocateVisitsCommandTest extends TestCase $visit = Visit::forValidShortUrl(ShortUrl::createEmpty(), new Visitor('', '', '1.2.3.4', '')); $location = VisitLocation::fromGeolocation(Location::emptyInstance()); - $locateVisits = $this->visitService->locateUnlocatedVisits(Argument::cetera())->will( - $this->invokeHelperMethods($visit, $location), - ); - $resolveIpLocation = $this->visitToLocation->resolveVisitLocation(Argument::any())->willThrow( + $this->lock->method('acquire')->with($this->isFalse())->willReturn(true); + $this->visitService->expects($this->once()) + ->method('locateUnlocatedVisits') + ->withAnyParameters() + ->willReturnCallback($this->invokeHelperMethods($visit, $location)); + $this->visitToLocation->expects($this->once())->method('resolveVisitLocation')->willThrowException( IpCannotBeLocatedException::forError(WrongIpException::fromIpAddress('1.2.3.4')), ); $this->downloadDbCommand->method('run')->withAnyParameters()->willReturn(ExitCodes::EXIT_SUCCESS); @@ -162,16 +157,11 @@ class LocateVisitsCommandTest extends TestCase $output = $this->commandTester->getDisplay(); self::assertStringContainsString('An error occurred while locating IP. Skipped', $output); - $locateVisits->shouldHaveBeenCalledOnce(); - $resolveIpLocation->shouldHaveBeenCalledOnce(); } private function invokeHelperMethods(Visit $visit, VisitLocation $location): callable { - return function (array $args) use ($visit, $location): void { - /** @var VisitGeolocationHelperInterface $helper */ - [$helper] = $args; - + return static function (VisitGeolocationHelperInterface $helper) use ($visit, $location): void { $helper->geolocateVisit($visit); $helper->onVisitLocated($location, $visit); }; @@ -180,11 +170,10 @@ class LocateVisitsCommandTest extends TestCase /** @test */ public function noActionIsPerformedIfLockIsAcquired(): void { - $this->lock->acquire(false)->willReturn(false); + $this->lock->method('acquire')->with($this->isFalse())->willReturn(false); - $locateVisits = $this->visitService->locateUnlocatedVisits(Argument::cetera())->will(function (): void { - }); - $resolveIpLocation = $this->visitToLocation->resolveVisitLocation(Argument::any()); + $this->visitService->expects($this->never())->method('locateUnlocatedVisits'); + $this->visitToLocation->expects($this->never())->method('resolveVisitLocation'); $this->downloadDbCommand->method('run')->withAnyParameters()->willReturn(ExitCodes::EXIT_SUCCESS); $this->commandTester->execute([], ['verbosity' => OutputInterface::VERBOSITY_VERBOSE]); @@ -194,25 +183,25 @@ class LocateVisitsCommandTest extends TestCase sprintf('Command "%s" is already in progress. Skipping.', LocateVisitsCommand::NAME), $output, ); - $locateVisits->shouldNotHaveBeenCalled(); - $resolveIpLocation->shouldNotHaveBeenCalled(); } /** @test */ public function showsProperMessageWhenGeoLiteUpdateFails(): void { + $this->lock->method('acquire')->with($this->isFalse())->willReturn(true); $this->downloadDbCommand->method('run')->withAnyParameters()->willReturn(ExitCodes::EXIT_FAILURE); + $this->visitService->expects($this->never())->method('locateUnlocatedVisits'); $this->commandTester->execute([]); $output = $this->commandTester->getDisplay(); self::assertStringContainsString('It is not possible to locate visits without a GeoLite2 db file.', $output); - $this->visitService->locateUnlocatedVisits(Argument::cetera())->shouldNotHaveBeenCalled(); } /** @test */ public function providingAllFlagOnItsOwnDisplaysNotice(): void { + $this->lock->method('acquire')->with($this->isFalse())->willReturn(true); $this->downloadDbCommand->method('run')->withAnyParameters()->willReturn(ExitCodes::EXIT_SUCCESS); $this->commandTester->execute(['--all' => true]);