From 736ac8ba90c7a4b06e149338e5fda91377218e6c Mon Sep 17 00:00:00 2001 From: Alejandro Celaya Date: Sat, 22 Oct 2022 07:54:57 +0200 Subject: [PATCH] Migrated LocateVisitTest to use PHPUnit mocks --- .../test/EventDispatcher/LocateVisitTest.php | 198 +++++++++--------- 1 file changed, 95 insertions(+), 103 deletions(-) diff --git a/module/Core/test/EventDispatcher/LocateVisitTest.php b/module/Core/test/EventDispatcher/LocateVisitTest.php index 068df028..b90b5b7f 100644 --- a/module/Core/test/EventDispatcher/LocateVisitTest.php +++ b/module/Core/test/EventDispatcher/LocateVisitTest.php @@ -6,10 +6,8 @@ namespace ShlinkioTest\Shlink\Core\EventDispatcher; use Doctrine\ORM\EntityManagerInterface; use OutOfRangeException; +use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; -use Prophecy\Argument; -use Prophecy\PhpUnit\ProphecyTrait; -use Prophecy\Prophecy\ObjectProphecy; use Psr\EventDispatcher\EventDispatcherInterface; use Psr\Log\LoggerInterface; use Shlinkio\Shlink\Common\Util\IpAddress; @@ -27,31 +25,27 @@ use Shlinkio\Shlink\IpGeolocation\Resolver\IpLocationResolverInterface; class LocateVisitTest extends TestCase { - use ProphecyTrait; - private LocateVisit $locateVisit; - private ObjectProphecy $ipLocationResolver; - private ObjectProphecy $em; - private ObjectProphecy $logger; - private ObjectProphecy $dbUpdater; - private ObjectProphecy $eventDispatcher; + private MockObject $ipLocationResolver; + private MockObject $em; + private MockObject $logger; + private MockObject $eventDispatcher; + private MockObject $dbUpdater; protected function setUp(): void { - $this->ipLocationResolver = $this->prophesize(IpLocationResolverInterface::class); - $this->em = $this->prophesize(EntityManagerInterface::class); - $this->logger = $this->prophesize(LoggerInterface::class); - $this->eventDispatcher = $this->prophesize(EventDispatcherInterface::class); - - $this->dbUpdater = $this->prophesize(DbUpdaterInterface::class); - $this->dbUpdater->databaseFileExists()->willReturn(true); + $this->ipLocationResolver = $this->createMock(IpLocationResolverInterface::class); + $this->em = $this->createMock(EntityManagerInterface::class); + $this->logger = $this->createMock(LoggerInterface::class); + $this->eventDispatcher = $this->createMock(EventDispatcherInterface::class); + $this->dbUpdater = $this->createMock(DbUpdaterInterface::class); $this->locateVisit = new LocateVisit( - $this->ipLocationResolver->reveal(), - $this->em->reveal(), - $this->logger->reveal(), - $this->dbUpdater->reveal(), - $this->eventDispatcher->reveal(), + $this->ipLocationResolver, + $this->em, + $this->logger, + $this->dbUpdater, + $this->eventDispatcher, ); } @@ -59,97 +53,91 @@ class LocateVisitTest extends TestCase public function invalidVisitLogsWarning(): void { $event = new UrlVisited('123'); - $findVisit = $this->em->find(Visit::class, '123')->willReturn(null); - $logWarning = $this->logger->warning('Tried to locate visit with id "{visitId}", but it does not exist.', [ - 'visitId' => 123, - ]); - $dispatch = $this->eventDispatcher->dispatch(new VisitLocated('123'))->will(function (): void { - }); + $this->em->expects($this->once())->method('find')->with( + $this->equalTo(Visit::class), + $this->equalTo('123'), + )->willReturn(null); + $this->em->expects($this->never())->method('flush'); + $this->logger->expects($this->once())->method('warning')->with( + $this->equalTo('Tried to locate visit with id "{visitId}", but it does not exist.'), + $this->equalTo(['visitId' => 123]), + ); + $this->eventDispatcher->expects($this->never())->method('dispatch')->with( + $this->equalTo(new VisitLocated('123')), + ); + $this->ipLocationResolver->expects($this->never())->method('resolveIpLocation'); ($this->locateVisit)($event); - - $findVisit->shouldHaveBeenCalledOnce(); - $this->em->flush()->shouldNotHaveBeenCalled(); - $this->ipLocationResolver->resolveIpLocation(Argument::cetera())->shouldNotHaveBeenCalled(); - $logWarning->shouldHaveBeenCalled(); - $dispatch->shouldNotHaveBeenCalled(); } /** @test */ public function nonExistingGeoLiteDbLogsWarning(): void { $event = new UrlVisited('123'); - $findVisit = $this->em->find(Visit::class, '123')->willReturn( - Visit::forValidShortUrl(ShortUrl::createEmpty(), new Visitor('', '', '1.2.3.4', '')), + $this->em->expects($this->once())->method('find')->with( + $this->equalTo(Visit::class), + $this->equalTo('123'), + )->willReturn(Visit::forValidShortUrl(ShortUrl::createEmpty(), new Visitor('', '', '1.2.3.4', ''))); + $this->em->expects($this->never())->method('flush'); + $this->dbUpdater->expects($this->once())->method('databaseFileExists')->withAnyParameters()->willReturn(false); + $this->logger->expects($this->once())->method('warning')->with( + $this->equalTo('Tried to locate visit with id "{visitId}", but a GeoLite2 db was not found.'), + $this->equalTo(['visitId' => 123]), ); - $dbExists = $this->dbUpdater->databaseFileExists()->willReturn(false); - $logWarning = $this->logger->warning( - 'Tried to locate visit with id "{visitId}", but a GeoLite2 db was not found.', - ['visitId' => 123], + $this->eventDispatcher->expects($this->once())->method('dispatch')->with( + $this->equalTo(new VisitLocated('123')), ); - $dispatch = $this->eventDispatcher->dispatch(new VisitLocated('123'))->will(function (): void { - }); + $this->ipLocationResolver->expects($this->never())->method('resolveIpLocation'); ($this->locateVisit)($event); - - $findVisit->shouldHaveBeenCalledOnce(); - $dbExists->shouldHaveBeenCalledOnce(); - $this->em->flush()->shouldNotHaveBeenCalled(); - $this->ipLocationResolver->resolveIpLocation(Argument::cetera())->shouldNotHaveBeenCalled(); - $logWarning->shouldHaveBeenCalled(); - $dispatch->shouldHaveBeenCalledOnce(); } /** @test */ public function invalidAddressLogsWarning(): void { $event = new UrlVisited('123'); - $findVisit = $this->em->find(Visit::class, '123')->willReturn( - Visit::forValidShortUrl(ShortUrl::createEmpty(), new Visitor('', '', '1.2.3.4', '')), + $this->em->expects($this->once())->method('find')->with( + $this->equalTo(Visit::class), + $this->equalTo('123'), + )->willReturn(Visit::forValidShortUrl(ShortUrl::createEmpty(), new Visitor('', '', '1.2.3.4', ''))); + $this->em->expects($this->never())->method('flush'); + $this->dbUpdater->expects($this->once())->method('databaseFileExists')->withAnyParameters()->willReturn(true); + $this->ipLocationResolver->expects( + $this->once(), + )->method('resolveIpLocation')->withAnyParameters()->willThrowException(WrongIpException::fromIpAddress('')); + $this->logger->expects($this->once())->method('warning')->with( + $this->equalTo('Tried to locate visit with id "{visitId}", but its address seems to be wrong. {e}'), + $this->isType('array'), ); - $resolveLocation = $this->ipLocationResolver->resolveIpLocation(Argument::cetera())->willThrow( - WrongIpException::class, + $this->eventDispatcher->expects($this->once())->method('dispatch')->with( + $this->equalTo(new VisitLocated('123')), ); - $logWarning = $this->logger->warning( - 'Tried to locate visit with id "{visitId}", but its address seems to be wrong. {e}', - Argument::type('array'), - ); - $dispatch = $this->eventDispatcher->dispatch(new VisitLocated('123'))->will(function (): void { - }); ($this->locateVisit)($event); - - $findVisit->shouldHaveBeenCalledOnce(); - $resolveLocation->shouldHaveBeenCalledOnce(); - $logWarning->shouldHaveBeenCalled(); - $this->em->flush()->shouldNotHaveBeenCalled(); - $dispatch->shouldHaveBeenCalledOnce(); } /** @test */ public function unhandledExceptionLogsError(): void { $event = new UrlVisited('123'); - $findVisit = $this->em->find(Visit::class, '123')->willReturn( - Visit::forValidShortUrl(ShortUrl::createEmpty(), new Visitor('', '', '1.2.3.4', '')), + $this->em->expects($this->once())->method('find')->with( + $this->equalTo(Visit::class), + $this->equalTo('123'), + )->willReturn(Visit::forValidShortUrl(ShortUrl::createEmpty(), new Visitor('', '', '1.2.3.4', ''))); + $this->em->expects($this->never())->method('flush'); + $this->dbUpdater->expects($this->once())->method('databaseFileExists')->withAnyParameters()->willReturn(true); + $this->ipLocationResolver->expects( + $this->once(), + )->method('resolveIpLocation')->withAnyParameters()->willThrowException(new OutOfRangeException()); + $this->logger->expects($this->once())->method('error')->with( + $this->equalTo('An unexpected error occurred while trying to locate visit with id "{visitId}". {e}'), + $this->isType('array'), ); - $resolveLocation = $this->ipLocationResolver->resolveIpLocation(Argument::cetera())->willThrow( - OutOfRangeException::class, + $this->eventDispatcher->expects($this->once())->method('dispatch')->with( + $this->equalTo(new VisitLocated('123')), ); - $logError = $this->logger->error( - 'An unexpected error occurred while trying to locate visit with id "{visitId}". {e}', - Argument::type('array'), - ); - $dispatch = $this->eventDispatcher->dispatch(new VisitLocated('123'))->will(function (): void { - }); ($this->locateVisit)($event); - - $findVisit->shouldHaveBeenCalledOnce(); - $resolveLocation->shouldHaveBeenCalledOnce(); - $logError->shouldHaveBeenCalled(); - $this->em->flush()->shouldNotHaveBeenCalled(); - $dispatch->shouldHaveBeenCalledOnce(); } /** @@ -159,21 +147,22 @@ class LocateVisitTest extends TestCase public function nonLocatableVisitsResolveToEmptyLocations(Visit $visit): void { $event = new UrlVisited('123'); - $findVisit = $this->em->find(Visit::class, '123')->willReturn($visit); - $flush = $this->em->flush()->will(function (): void { - }); - $resolveIp = $this->ipLocationResolver->resolveIpLocation(Argument::any()); - $dispatch = $this->eventDispatcher->dispatch(new VisitLocated('123'))->will(function (): void { - }); + $this->em->expects($this->once())->method('find')->with( + $this->equalTo(Visit::class), + $this->equalTo('123'), + )->willReturn($visit); + $this->em->expects($this->once())->method('flush'); + $this->dbUpdater->expects($this->once())->method('databaseFileExists')->withAnyParameters()->willReturn(true); + $this->ipLocationResolver->expects($this->never())->method('resolveIpLocation'); + + $this->eventDispatcher->expects($this->once())->method('dispatch')->with( + $this->equalTo(new VisitLocated('123')), + ); + $this->logger->expects($this->never())->method('warning'); ($this->locateVisit)($event); self::assertEquals($visit->getVisitLocation(), VisitLocation::fromGeolocation(Location::emptyInstance())); - $findVisit->shouldHaveBeenCalledOnce(); - $flush->shouldHaveBeenCalledOnce(); - $resolveIp->shouldNotHaveBeenCalled(); - $this->logger->warning(Argument::cetera())->shouldNotHaveBeenCalled(); - $dispatch->shouldHaveBeenCalledOnce(); } public function provideNonLocatableVisits(): iterable @@ -195,21 +184,24 @@ class LocateVisitTest extends TestCase $location = new Location('', '', '', '', 0.0, 0.0, ''); $event = UrlVisited::withOriginalIpAddress('123', $originalIpAddress); - $findVisit = $this->em->find(Visit::class, '123')->willReturn($visit); - $flush = $this->em->flush()->will(function (): void { - }); - $resolveIp = $this->ipLocationResolver->resolveIpLocation($ipAddr)->willReturn($location); - $dispatch = $this->eventDispatcher->dispatch(new VisitLocated('123'))->will(function (): void { - }); + $this->em->expects($this->once())->method('find')->with( + $this->equalTo(Visit::class), + $this->equalTo('123'), + )->willReturn($visit); + $this->em->expects($this->once())->method('flush'); + $this->dbUpdater->expects($this->once())->method('databaseFileExists')->withAnyParameters()->willReturn(true); + $this->ipLocationResolver->expects($this->once())->method('resolveIpLocation')->with( + $this->equalTo($ipAddr), + )->willReturn($location); + + $this->eventDispatcher->expects($this->once())->method('dispatch')->with( + $this->equalTo(new VisitLocated('123')), + ); + $this->logger->expects($this->never())->method('warning'); ($this->locateVisit)($event); self::assertEquals($visit->getVisitLocation(), VisitLocation::fromGeolocation($location)); - $findVisit->shouldHaveBeenCalledOnce(); - $flush->shouldHaveBeenCalledOnce(); - $resolveIp->shouldHaveBeenCalledOnce(); - $this->logger->warning(Argument::cetera())->shouldNotHaveBeenCalled(); - $dispatch->shouldHaveBeenCalledOnce(); } public function provideIpAddresses(): iterable