diff --git a/CHANGELOG.md b/CHANGELOG.md index 80a6dc66..6d6c7aa5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com), and this ### Changed * [#1563](https://github.com/shlinkio/shlink/issues/1563) Moved logic to reuse command options to option classes instead of base abstract command classes. +* [#1569](https://github.com/shlinkio/shlink/issues/1569) Migrated test doubles from phpspec/prophecy to PHPUnit mocks. ### Deprecated * *Nothing* diff --git a/composer.json b/composer.json index 5f72b1db..cdf2c42e 100644 --- a/composer.json +++ b/composer.json @@ -65,7 +65,6 @@ "dms/phpunit-arraysubset-asserts": "^0.4.0", "infection/infection": "^0.26.15", "openswoole/ide-helper": "~4.11.5", - "phpspec/prophecy-phpunit": "^2.0", "phpstan/phpstan": "^1.8", "phpstan/phpstan-doctrine": "^1.3", "phpstan/phpstan-symfony": "^1.2", diff --git a/module/Core/test/Tag/Paginator/Adapter/TagsInfoPaginatorAdapterTest.php b/module/Core/test/Tag/Paginator/Adapter/TagsInfoPaginatorAdapterTest.php index f2f573a4..99ebddf1 100644 --- a/module/Core/test/Tag/Paginator/Adapter/TagsInfoPaginatorAdapterTest.php +++ b/module/Core/test/Tag/Paginator/Adapter/TagsInfoPaginatorAdapterTest.php @@ -4,45 +4,37 @@ declare(strict_types=1); namespace ShlinkioTest\Shlink\Core\Tag\Paginator\Adapter; +use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; -use Prophecy\Argument; -use Prophecy\PhpUnit\ProphecyTrait; -use Prophecy\Prophecy\ObjectProphecy; use Shlinkio\Shlink\Core\Tag\Model\TagsParams; use Shlinkio\Shlink\Core\Tag\Paginator\Adapter\TagsInfoPaginatorAdapter; use Shlinkio\Shlink\Core\Tag\Repository\TagRepositoryInterface; class TagsInfoPaginatorAdapterTest extends TestCase { - use ProphecyTrait; - private TagsInfoPaginatorAdapter $adapter; - private ObjectProphecy $repo; + private MockObject $repo; protected function setUp(): void { - $this->repo = $this->prophesize(TagRepositoryInterface::class); - $this->adapter = new TagsInfoPaginatorAdapter($this->repo->reveal(), TagsParams::fromRawData([]), null); + $this->repo = $this->createMock(TagRepositoryInterface::class); + $this->adapter = new TagsInfoPaginatorAdapter($this->repo, TagsParams::fromRawData([]), null); } /** @test */ public function getSliceIsDelegatedToRepository(): void { - $findTags = $this->repo->findTagsWithInfo(Argument::cetera())->willReturn([]); - + $this->repo->expects($this->once())->method('findTagsWithInfo')->willReturn([]); $this->adapter->getSlice(1, 1); - - $findTags->shouldHaveBeenCalledOnce(); } /** @test */ public function getNbResultsIsDelegatedToRepository(): void { - $match = $this->repo->matchSingleScalarResult(Argument::cetera())->willReturn(3); + $this->repo->expects($this->once())->method('matchSingleScalarResult')->willReturn(3); $result = $this->adapter->getNbResults(); self::assertEquals(3, $result); - $match->shouldHaveBeenCalledOnce(); } } diff --git a/module/Core/test/Tag/Paginator/Adapter/TagsPaginatorAdapterTest.php b/module/Core/test/Tag/Paginator/Adapter/TagsPaginatorAdapterTest.php index ccad1ec1..bce7d9cc 100644 --- a/module/Core/test/Tag/Paginator/Adapter/TagsPaginatorAdapterTest.php +++ b/module/Core/test/Tag/Paginator/Adapter/TagsPaginatorAdapterTest.php @@ -4,34 +4,27 @@ declare(strict_types=1); namespace ShlinkioTest\Shlink\Core\Tag\Paginator\Adapter; +use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; -use Prophecy\Argument; -use Prophecy\PhpUnit\ProphecyTrait; -use Prophecy\Prophecy\ObjectProphecy; use Shlinkio\Shlink\Core\Tag\Model\TagsParams; use Shlinkio\Shlink\Core\Tag\Paginator\Adapter\TagsPaginatorAdapter; use Shlinkio\Shlink\Core\Tag\Repository\TagRepositoryInterface; class TagsPaginatorAdapterTest extends TestCase { - use ProphecyTrait; - private TagsPaginatorAdapter $adapter; - private ObjectProphecy $repo; + private MockObject $repo; protected function setUp(): void { - $this->repo = $this->prophesize(TagRepositoryInterface::class); - $this->adapter = new TagsPaginatorAdapter($this->repo->reveal(), TagsParams::fromRawData([]), null); + $this->repo = $this->createMock(TagRepositoryInterface::class); + $this->adapter = new TagsPaginatorAdapter($this->repo, TagsParams::fromRawData([]), null); } /** @test */ public function getSliceDelegatesToRepository(): void { - $match = $this->repo->match(Argument::cetera())->willReturn([]); - + $this->repo->expects($this->once())->method('match')->willReturn([]); $this->adapter->getSlice(1, 1); - - $match->shouldHaveBeenCalledOnce(); } } diff --git a/module/Core/test/Tag/TagServiceTest.php b/module/Core/test/Tag/TagServiceTest.php index 59d22bba..9cba4875 100644 --- a/module/Core/test/Tag/TagServiceTest.php +++ b/module/Core/test/Tag/TagServiceTest.php @@ -5,10 +5,8 @@ declare(strict_types=1); namespace ShlinkioTest\Shlink\Core\Tag; use Doctrine\ORM\EntityManagerInterface; +use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; -use Prophecy\Argument; -use Prophecy\PhpUnit\ProphecyTrait; -use Prophecy\Prophecy\ObjectProphecy; use Shlinkio\Shlink\Core\Exception\ForbiddenTagOperationException; use Shlinkio\Shlink\Core\Exception\TagConflictException; use Shlinkio\Shlink\Core\Exception\TagNotFoundException; @@ -27,19 +25,18 @@ use ShlinkioTest\Shlink\Core\Util\ApiKeyHelpersTrait; class TagServiceTest extends TestCase { use ApiKeyHelpersTrait; - use ProphecyTrait; private TagService $service; - private ObjectProphecy $em; - private ObjectProphecy $repo; + private MockObject $em; + private MockObject $repo; protected function setUp(): void { - $this->em = $this->prophesize(EntityManagerInterface::class); - $this->repo = $this->prophesize(TagRepository::class); - $this->em->getRepository(Tag::class)->willReturn($this->repo->reveal()); + $this->em = $this->createMock(EntityManagerInterface::class); + $this->repo = $this->createMock(TagRepository::class); + $this->em->method('getRepository')->with(Tag::class)->willReturn($this->repo); - $this->service = new TagService($this->em->reveal()); + $this->service = new TagService($this->em); } /** @test */ @@ -47,14 +44,12 @@ class TagServiceTest extends TestCase { $expected = [new Tag('foo'), new Tag('bar')]; - $match = $this->repo->match(Argument::cetera())->willReturn($expected); - $count = $this->repo->matchSingleScalarResult(Argument::cetera())->willReturn(2); + $this->repo->expects($this->once())->method('match')->willReturn($expected); + $this->repo->expects($this->once())->method('matchSingleScalarResult')->willReturn(2); $result = $this->service->listTags(TagsParams::fromRawData([])); self::assertEquals($expected, $result->getCurrentPageResults()); - $match->shouldHaveBeenCalled(); - $count->shouldHaveBeenCalled(); } /** @@ -69,14 +64,14 @@ class TagServiceTest extends TestCase ): void { $expected = [new TagInfo('foo', 1, 1), new TagInfo('bar', 3, 10)]; - $find = $this->repo->findTagsWithInfo($expectedFiltering)->willReturn($expected); - $count = $this->repo->matchSingleScalarResult(Argument::cetera())->willReturn(2); + $this->repo->expects($this->once())->method('findTagsWithInfo')->with($expectedFiltering)->willReturn( + $expected, + ); + $this->repo->expects($this->exactly($countCalls))->method('matchSingleScalarResult')->willReturn(2); $result = $this->service->tagsInfo($params, $apiKey); self::assertEquals($expected, $result->getCurrentPageResults()); - $find->shouldHaveBeenCalledOnce(); - $count->shouldHaveBeenCalledTimes($countCalls); } public function provideApiKeysAndSearchTerm(): iterable @@ -113,21 +108,17 @@ class TagServiceTest extends TestCase */ public function deleteTagsDelegatesOnRepository(?ApiKey $apiKey): void { - $delete = $this->repo->deleteByName(['foo', 'bar'])->willReturn(4); - + $this->repo->expects($this->once())->method('deleteByName')->with(['foo', 'bar'])->willReturn(4); $this->service->deleteTags(['foo', 'bar'], $apiKey); - - $delete->shouldHaveBeenCalled(); } /** @test */ public function deleteTagsThrowsExceptionWhenProvidedApiKeyIsNotAdmin(): void { - $delete = $this->repo->deleteByName(['foo', 'bar']); + $this->repo->expects($this->never())->method('deleteByName'); $this->expectException(ForbiddenTagOperationException::class); $this->expectExceptionMessage('You are not allowed to delete tags'); - $delete->shouldNotBeCalled(); $this->service->deleteTags( ['foo', 'bar'], @@ -141,9 +132,7 @@ class TagServiceTest extends TestCase */ public function renameInvalidTagThrowsException(?ApiKey $apiKey): void { - $find = $this->repo->findOneBy(Argument::cetera())->willReturn(null); - - $find->shouldBeCalled(); + $this->repo->expects($this->once())->method('findOneBy')->willReturn(null); $this->expectException(TagNotFoundException::class); $this->service->renameTag(TagRenaming::fromNames('foo', 'bar'), $apiKey); @@ -157,17 +146,14 @@ class TagServiceTest extends TestCase { $expected = new Tag('foo'); - $find = $this->repo->findOneBy(Argument::cetera())->willReturn($expected); - $countTags = $this->repo->count(Argument::cetera())->willReturn($count); - $flush = $this->em->flush()->willReturn(null); + $this->repo->expects($this->once())->method('findOneBy')->willReturn($expected); + $this->repo->expects($this->exactly($count > 0 ? 0 : 1))->method('count')->willReturn($count); + $this->em->expects($this->once())->method('flush'); $tag = $this->service->renameTag(TagRenaming::fromNames($oldName, $newName)); self::assertSame($expected, $tag); self::assertEquals($newName, (string) $tag); - $find->shouldHaveBeenCalled(); - $flush->shouldHaveBeenCalled(); - $countTags->shouldHaveBeenCalledTimes($count > 0 ? 0 : 1); } public function provideValidRenames(): iterable @@ -182,13 +168,10 @@ class TagServiceTest extends TestCase */ public function renameTagToAnExistingNameThrowsException(?ApiKey $apiKey): void { - $find = $this->repo->findOneBy(Argument::cetera())->willReturn(new Tag('foo')); - $countTags = $this->repo->count(Argument::cetera())->willReturn(1); - $flush = $this->em->flush(Argument::any())->willReturn(null); + $this->repo->expects($this->once())->method('findOneBy')->willReturn(new Tag('foo')); + $this->repo->expects($this->once())->method('count')->willReturn(1); + $this->em->expects($this->never())->method('flush'); - $find->shouldBeCalled(); - $countTags->shouldBeCalled(); - $flush->shouldNotBeCalled(); $this->expectException(TagConflictException::class); $this->service->renameTag(TagRenaming::fromNames('foo', 'bar'), $apiKey); @@ -197,11 +180,10 @@ class TagServiceTest extends TestCase /** @test */ public function renamingTagThrowsExceptionWhenProvidedApiKeyIsNotAdmin(): void { - $getRepo = $this->em->getRepository(Tag::class); + $this->em->expects($this->never())->method('getRepository')->with(Tag::class); $this->expectExceptionMessage(ForbiddenTagOperationException::class); $this->expectExceptionMessage('You are not allowed to rename tags'); - $getRepo->shouldNotBeCalled(); $this->service->renameTag( TagRenaming::fromNames('foo', 'bar'), diff --git a/module/Core/test/Util/DoctrineBatchHelperTest.php b/module/Core/test/Util/DoctrineBatchHelperTest.php index f6f9981d..aec4f0b6 100644 --- a/module/Core/test/Util/DoctrineBatchHelperTest.php +++ b/module/Core/test/Util/DoctrineBatchHelperTest.php @@ -5,23 +5,20 @@ declare(strict_types=1); namespace ShlinkioTest\Shlink\Core\Util; use Doctrine\ORM\EntityManagerInterface; +use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; -use Prophecy\PhpUnit\ProphecyTrait; -use Prophecy\Prophecy\ObjectProphecy; use RuntimeException; use Shlinkio\Shlink\Core\Util\DoctrineBatchHelper; class DoctrineBatchHelperTest extends TestCase { - use ProphecyTrait; - private DoctrineBatchHelper $helper; - private ObjectProphecy $em; + private MockObject $em; protected function setUp(): void { - $this->em = $this->prophesize(EntityManagerInterface::class); - $this->helper = new DoctrineBatchHelper($this->em->reveal()); + $this->em = $this->createMock(EntityManagerInterface::class); + $this->helper = new DoctrineBatchHelper($this->em); } /** @@ -33,17 +30,17 @@ class DoctrineBatchHelperTest extends TestCase int $batchSize, int $expectedCalls, ): void { + $this->em->expects($this->once())->method('beginTransaction'); + $this->em->expects($this->once())->method('commit'); + $this->em->expects($this->never())->method('rollback'); + $this->em->expects($this->exactly($expectedCalls))->method('flush'); + $this->em->expects($this->exactly($expectedCalls))->method('clear'); + $wrappedIterable = $this->helper->wrapIterable($iterable, $batchSize); foreach ($wrappedIterable as $item) { // Iterable needs to be iterated for the logic to be invoked } - - $this->em->beginTransaction()->shouldHaveBeenCalledOnce(); - $this->em->commit()->shouldHaveBeenCalledOnce(); - $this->em->rollback()->shouldNotHaveBeenCalled(); - $this->em->flush()->shouldHaveBeenCalledTimes($expectedCalls); - $this->em->clear()->shouldHaveBeenCalledTimes($expectedCalls); } public function provideIterables(): iterable @@ -56,15 +53,14 @@ class DoctrineBatchHelperTest extends TestCase /** @test */ public function transactionIsRolledBackWhenAnErrorOccurs(): void { - $flush = $this->em->flush()->willThrow(RuntimeException::class); + $this->em->expects($this->once())->method('flush')->willThrowException(new RuntimeException()); + $this->em->expects($this->once())->method('beginTransaction'); + $this->em->expects($this->never())->method('commit'); + $this->em->expects($this->once())->method('rollback'); $wrappedIterable = $this->helper->wrapIterable([1, 2, 3], 1); self::expectException(RuntimeException::class); - $flush->shouldBeCalledOnce(); - $this->em->beginTransaction()->shouldBeCalledOnce(); - $this->em->commit()->shouldNotBeCalled(); - $this->em->rollback()->shouldBeCalledOnce(); foreach ($wrappedIterable as $item) { // Iterable needs to be iterated for the logic to be invoked diff --git a/module/Core/test/Util/UrlValidatorTest.php b/module/Core/test/Util/UrlValidatorTest.php index cc13bd2c..2610b7fd 100644 --- a/module/Core/test/Util/UrlValidatorTest.php +++ b/module/Core/test/Util/UrlValidatorTest.php @@ -7,35 +7,30 @@ namespace ShlinkioTest\Shlink\Core\Util; use Fig\Http\Message\RequestMethodInterface; use GuzzleHttp\ClientInterface; use GuzzleHttp\Exception\ClientException; +use GuzzleHttp\Psr7\Request; use GuzzleHttp\RequestOptions; use Laminas\Diactoros\Response; use Laminas\Diactoros\Stream; use PHPUnit\Framework\Assert; +use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; -use Prophecy\Argument; -use Prophecy\PhpUnit\ProphecyTrait; -use Prophecy\Prophecy\ObjectProphecy; use Shlinkio\Shlink\Core\Exception\InvalidUrlException; use Shlinkio\Shlink\Core\Options\UrlShortenerOptions; use Shlinkio\Shlink\Core\Util\UrlValidator; class UrlValidatorTest extends TestCase { - use ProphecyTrait; - - private ObjectProphecy $httpClient; + private MockObject $httpClient; protected function setUp(): void { - $this->httpClient = $this->prophesize(ClientInterface::class); + $this->httpClient = $this->createMock(ClientInterface::class); } /** @test */ public function exceptionIsThrownWhenUrlIsInvalid(): void { - $request = $this->httpClient->request(Argument::cetera())->willThrow(ClientException::class); - - $request->shouldBeCalledOnce(); + $this->httpClient->expects($this->once())->method('request')->willThrowException($this->clientException()); $this->expectException(InvalidUrlException::class); $this->urlValidator()->validateUrl('http://foobar.com/12345/hello?foo=bar', true); @@ -46,10 +41,10 @@ class UrlValidatorTest extends TestCase { $expectedUrl = 'http://foobar.com'; - $request = $this->httpClient->request( + $this->httpClient->expects($this->once())->method('request')->with( RequestMethodInterface::METHOD_GET, $expectedUrl, - Argument::that(function (array $options) { + $this->callback(function (array $options) { Assert::assertArrayHasKey(RequestOptions::ALLOW_REDIRECTS, $options); Assert::assertEquals(['max' => 15], $options[RequestOptions::ALLOW_REDIRECTS]); Assert::assertArrayHasKey(RequestOptions::IDN_CONVERSION, $options); @@ -62,92 +57,91 @@ class UrlValidatorTest extends TestCase )->willReturn(new Response()); $this->urlValidator()->validateUrl($expectedUrl, true); - - $request->shouldHaveBeenCalledOnce(); } /** @test */ public function noCheckIsPerformedWhenUrlValidationIsDisabled(): void { - $request = $this->httpClient->request(Argument::cetera())->willReturn(new Response()); - + $this->httpClient->expects($this->never())->method('request'); $this->urlValidator()->validateUrl('', false); - - $request->shouldNotHaveBeenCalled(); } /** @test */ public function validateUrlWithTitleReturnsNullWhenRequestFailsAndValidationIsDisabled(): void { - $request = $this->httpClient->request(Argument::cetera())->willThrow(ClientException::class); + $this->httpClient->expects($this->once())->method('request')->willThrowException($this->clientException()); $result = $this->urlValidator(true)->validateUrlWithTitle('http://foobar.com/12345/hello?foo=bar', false); self::assertNull($result); - $request->shouldHaveBeenCalledOnce(); } /** @test */ public function validateUrlWithTitleReturnsNullWhenAutoResolutionIsDisabled(): void { - $request = $this->httpClient->request(Argument::cetera())->willReturn($this->respWithTitle()); + $this->httpClient->expects($this->never())->method('request'); $result = $this->urlValidator()->validateUrlWithTitle('http://foobar.com/12345/hello?foo=bar', false); self::assertNull($result); - $request->shouldNotHaveBeenCalled(); } /** @test */ public function validateUrlWithTitleReturnsNullWhenAutoResolutionIsDisabledAndValidationIsEnabled(): void { - $request = $this->httpClient->request(RequestMethodInterface::METHOD_HEAD, Argument::cetera())->willReturn( - $this->respWithTitle(), - ); + $this->httpClient->expects($this->once())->method('request')->with( + RequestMethodInterface::METHOD_HEAD, + $this->anything(), + $this->anything(), + )->willReturn($this->respWithTitle()); $result = $this->urlValidator()->validateUrlWithTitle('http://foobar.com/12345/hello?foo=bar', true); self::assertNull($result); - $request->shouldHaveBeenCalledOnce(); } /** @test */ public function validateUrlWithTitleResolvesTitleWhenAutoResolutionIsEnabled(): void { - $request = $this->httpClient->request(RequestMethodInterface::METHOD_GET, Argument::cetera())->willReturn( - $this->respWithTitle(), - ); + $this->httpClient->expects($this->once())->method('request')->with( + RequestMethodInterface::METHOD_GET, + $this->anything(), + $this->anything(), + )->willReturn($this->respWithTitle()); $result = $this->urlValidator(true)->validateUrlWithTitle('http://foobar.com/12345/hello?foo=bar', true); self::assertEquals('Resolved "title"', $result); - $request->shouldHaveBeenCalledOnce(); } /** @test */ public function validateUrlWithTitleReturnsNullWhenAutoResolutionIsEnabledAndReturnedContentTypeIsInvalid(): void { - $request = $this->httpClient->request(RequestMethodInterface::METHOD_GET, Argument::cetera())->willReturn( - new Response('php://memory', 200, ['Content-Type' => 'application/octet-stream']), - ); + $this->httpClient->expects($this->once())->method('request')->with( + RequestMethodInterface::METHOD_GET, + $this->anything(), + $this->anything(), + )->willReturn(new Response('php://memory', 200, ['Content-Type' => 'application/octet-stream'])); $result = $this->urlValidator(true)->validateUrlWithTitle('http://foobar.com/12345/hello?foo=bar', true); self::assertNull($result); - $request->shouldHaveBeenCalledOnce(); } /** @test */ public function validateUrlWithTitleReturnsNullWhenAutoResolutionIsEnabledAndBodyDoesNotContainTitle(): void { - $request = $this->httpClient->request(RequestMethodInterface::METHOD_GET, Argument::cetera())->willReturn( + $this->httpClient->expects($this->once())->method('request')->with( + RequestMethodInterface::METHOD_GET, + $this->anything(), + $this->anything(), + )->willReturn( new Response($this->createStreamWithContent('No title'), 200, ['Content-Type' => 'text/html']), ); $result = $this->urlValidator(true)->validateUrlWithTitle('http://foobar.com/12345/hello?foo=bar', true); self::assertNull($result); - $request->shouldHaveBeenCalledOnce(); } private function respWithTitle(): Response @@ -165,11 +159,17 @@ class UrlValidatorTest extends TestCase return $body; } - public function urlValidator(bool $autoResolveTitles = false): UrlValidator + private function clientException(): ClientException { - return new UrlValidator( - $this->httpClient->reveal(), - new UrlShortenerOptions(autoResolveTitles: $autoResolveTitles), + return new ClientException( + '', + new Request(RequestMethodInterface::METHOD_GET, ''), + new Response(), ); } + + public function urlValidator(bool $autoResolveTitles = false): UrlValidator + { + return new UrlValidator($this->httpClient, new UrlShortenerOptions(autoResolveTitles: $autoResolveTitles)); + } } diff --git a/module/Core/test/Visit/Geolocation/VisitLocatorTest.php b/module/Core/test/Visit/Geolocation/VisitLocatorTest.php index 6cdd421d..4141f7c5 100644 --- a/module/Core/test/Visit/Geolocation/VisitLocatorTest.php +++ b/module/Core/test/Visit/Geolocation/VisitLocatorTest.php @@ -7,11 +7,8 @@ namespace ShlinkioTest\Shlink\Core\Visit\Geolocation; use Doctrine\ORM\EntityManager; use Exception; use PHPUnit\Framework\Assert; +use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; -use Prophecy\Argument; -use Prophecy\PhpUnit\ProphecyTrait; -use Prophecy\Prophecy\MethodProphecy; -use Prophecy\Prophecy\ObjectProphecy; use Shlinkio\Shlink\Core\Exception\IpCannotBeLocatedException; use Shlinkio\Shlink\Core\ShortUrl\Entity\ShortUrl; use Shlinkio\Shlink\Core\Visit\Entity\Visit; @@ -32,19 +29,17 @@ use function sprintf; class VisitLocatorTest extends TestCase { - use ProphecyTrait; - private VisitLocator $visitService; - private ObjectProphecy $em; - private ObjectProphecy $repo; + private MockObject $em; + private MockObject $repo; protected function setUp(): void { - $this->em = $this->prophesize(EntityManager::class); - $this->repo = $this->prophesize(VisitRepositoryInterface::class); - $this->em->getRepository(Visit::class)->willReturn($this->repo->reveal()); + $this->em = $this->createMock(EntityManager::class); + $this->repo = $this->createMock(VisitRepositoryInterface::class); + $this->em->method('getRepository')->with(Visit::class)->willReturn($this->repo); - $this->visitService = new VisitLocator($this->em->reveal()); + $this->visitService = new VisitLocator($this->em); } /** @@ -61,14 +56,13 @@ class VisitLocatorTest extends TestCase Visit::forValidShortUrl(ShortUrl::withLongUrl(sprintf('short_code_%s', $i)), Visitor::emptyInstance()), ); - $findVisits = $this->mockRepoMethod($expectedRepoMethodName)->willReturn($unlocatedVisits); + $this->repo->expects($this->once())->method($expectedRepoMethodName)->willReturn($unlocatedVisits); - $persist = $this->em->persist(Argument::type(Visit::class))->will(function (): void { - }); - $flush = $this->em->flush()->will(function (): void { - }); - $clear = $this->em->clear()->will(function (): void { - }); + $this->em->expects($this->exactly(count($unlocatedVisits)))->method('persist')->with( + $this->isInstanceOf(Visit::class), + ); + $this->em->expects($this->exactly((int) floor(count($unlocatedVisits) / 200) + 1))->method('flush'); + $this->em->expects($this->exactly((int) floor(count($unlocatedVisits) / 200) + 1))->method('clear'); $this->visitService->{$serviceMethodName}(new class implements VisitGeolocationHelperInterface { public function geolocateVisit(Visit $visit): Location @@ -84,11 +78,6 @@ class VisitLocatorTest extends TestCase Assert::assertInstanceOf(Visit::class, array_shift($args)); } }); - - $findVisits->shouldHaveBeenCalledOnce(); - $persist->shouldHaveBeenCalledTimes(count($unlocatedVisits)); - $flush->shouldHaveBeenCalledTimes(floor(count($unlocatedVisits) / 200) + 1); - $clear->shouldHaveBeenCalledTimes(floor(count($unlocatedVisits) / 200) + 1); } public function provideMethodNames(): iterable @@ -111,14 +100,13 @@ class VisitLocatorTest extends TestCase Visit::forValidShortUrl(ShortUrl::withLongUrl('foo'), Visitor::emptyInstance()), ]; - $findVisits = $this->mockRepoMethod($expectedRepoMethodName)->willReturn($unlocatedVisits); + $this->repo->expects($this->once())->method($expectedRepoMethodName)->willReturn($unlocatedVisits); - $persist = $this->em->persist(Argument::type(Visit::class))->will(function (): void { - }); - $flush = $this->em->flush()->will(function (): void { - }); - $clear = $this->em->clear()->will(function (): void { - }); + $this->em->expects($this->exactly($isNonLocatableAddress ? 1 : 0))->method('persist')->with( + $this->isInstanceOf(Visit::class), + ); + $this->em->expects($this->once())->method('flush'); + $this->em->expects($this->once())->method('clear'); $this->visitService->{$serviceMethodName}( new class ($isNonLocatableAddress) implements VisitGeolocationHelperInterface { @@ -138,11 +126,6 @@ class VisitLocatorTest extends TestCase } }, ); - - $findVisits->shouldHaveBeenCalledOnce(); - $persist->shouldHaveBeenCalledTimes($isNonLocatableAddress ? 1 : 0); - $flush->shouldHaveBeenCalledOnce(); - $clear->shouldHaveBeenCalledOnce(); } public function provideIsNonLocatableAddress(): iterable @@ -162,9 +145,4 @@ class VisitLocatorTest extends TestCase yield 'locateAllVisits - locatable address' => ['locateAllVisits', 'findAllVisits', false]; yield 'locateAllVisits - non-locatable address' => ['locateAllVisits', 'findAllVisits', true]; } - - private function mockRepoMethod(string $methodName): MethodProphecy - { - return (new MethodProphecy($this->repo, $methodName, new Argument\ArgumentsWildcard([]))); - } } diff --git a/module/Core/test/Visit/Geolocation/VisitToLocationHelperTest.php b/module/Core/test/Visit/Geolocation/VisitToLocationHelperTest.php index 505a24dd..b32dc037 100644 --- a/module/Core/test/Visit/Geolocation/VisitToLocationHelperTest.php +++ b/module/Core/test/Visit/Geolocation/VisitToLocationHelperTest.php @@ -4,10 +4,8 @@ declare(strict_types=1); namespace ShlinkioTest\Shlink\Core\Visit\Geolocation; +use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; -use Prophecy\Argument; -use Prophecy\PhpUnit\ProphecyTrait; -use Prophecy\Prophecy\ObjectProphecy; use Shlinkio\Shlink\Common\Util\IpAddress; use Shlinkio\Shlink\Core\Exception\IpCannotBeLocatedException; use Shlinkio\Shlink\Core\Visit\Entity\Visit; @@ -18,15 +16,13 @@ use Shlinkio\Shlink\IpGeolocation\Resolver\IpLocationResolverInterface; class VisitToLocationHelperTest extends TestCase { - use ProphecyTrait; - private VisitToLocationHelper $helper; - private ObjectProphecy $ipLocationResolver; + private MockObject $ipLocationResolver; protected function setUp(): void { - $this->ipLocationResolver = $this->prophesize(IpLocationResolverInterface::class); - $this->helper = new VisitToLocationHelper($this->ipLocationResolver->reveal()); + $this->ipLocationResolver = $this->createMock(IpLocationResolverInterface::class); + $this->helper = new VisitToLocationHelper($this->ipLocationResolver); } /** @@ -38,7 +34,7 @@ class VisitToLocationHelperTest extends TestCase IpCannotBeLocatedException $expectedException, ): void { $this->expectExceptionObject($expectedException); - $this->ipLocationResolver->resolveIpLocation(Argument::cetera())->shouldNotBeCalled(); + $this->ipLocationResolver->expects($this->never())->method('resolveIpLocation'); $this->helper->resolveVisitLocation($visit); } @@ -58,8 +54,7 @@ class VisitToLocationHelperTest extends TestCase $e = new WrongIpException(''); $this->expectExceptionObject(IpCannotBeLocatedException::forError($e)); - $this->ipLocationResolver->resolveIpLocation(Argument::cetera())->willThrow($e) - ->shouldBeCalledOnce(); + $this->ipLocationResolver->expects($this->once())->method('resolveIpLocation')->willThrowException($e); $this->helper->resolveVisitLocation(Visit::forBasePath(new Visitor('foo', 'bar', '1.2.3.4', ''))); } diff --git a/module/Core/test/Visit/Paginator/Adapter/NonOrphanVisitsPaginatorAdapterTest.php b/module/Core/test/Visit/Paginator/Adapter/NonOrphanVisitsPaginatorAdapterTest.php index 0787cbba..1bd03109 100644 --- a/module/Core/test/Visit/Paginator/Adapter/NonOrphanVisitsPaginatorAdapterTest.php +++ b/module/Core/test/Visit/Paginator/Adapter/NonOrphanVisitsPaginatorAdapterTest.php @@ -4,9 +4,8 @@ declare(strict_types=1); namespace ShlinkioTest\Shlink\Core\Visit\Paginator\Adapter; +use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; -use Prophecy\PhpUnit\ProphecyTrait; -use Prophecy\Prophecy\ObjectProphecy; use Shlinkio\Shlink\Core\Visit\Entity\Visit; use Shlinkio\Shlink\Core\Visit\Model\Visitor; use Shlinkio\Shlink\Core\Visit\Model\VisitsParams; @@ -18,34 +17,31 @@ use Shlinkio\Shlink\Rest\Entity\ApiKey; class NonOrphanVisitsPaginatorAdapterTest extends TestCase { - use ProphecyTrait; - private NonOrphanVisitsPaginatorAdapter $adapter; - private ObjectProphecy $repo; + private MockObject $repo; private VisitsParams $params; private ApiKey $apiKey; protected function setUp(): void { - $this->repo = $this->prophesize(VisitRepositoryInterface::class); + $this->repo = $this->createMock(VisitRepositoryInterface::class); $this->params = VisitsParams::fromRawData([]); $this->apiKey = ApiKey::create(); - $this->adapter = new NonOrphanVisitsPaginatorAdapter($this->repo->reveal(), $this->params, $this->apiKey); + $this->adapter = new NonOrphanVisitsPaginatorAdapter($this->repo, $this->params, $this->apiKey); } /** @test */ public function countDelegatesToRepository(): void { $expectedCount = 5; - $repoCount = $this->repo->countNonOrphanVisits( + $this->repo->expects($this->once())->method('countNonOrphanVisits')->with( new VisitsCountFiltering($this->params->dateRange, $this->params->excludeBots, $this->apiKey), )->willReturn($expectedCount); $result = $this->adapter->getNbResults(); self::assertEquals($expectedCount, $result); - $repoCount->shouldHaveBeenCalledOnce(); } /** @@ -56,7 +52,7 @@ class NonOrphanVisitsPaginatorAdapterTest extends TestCase { $visitor = Visitor::emptyInstance(); $list = [Visit::forRegularNotFound($visitor), Visit::forInvalidShortUrl($visitor)]; - $repoFind = $this->repo->findNonOrphanVisits(new VisitsListFiltering( + $this->repo->expects($this->once())->method('findNonOrphanVisits')->with(new VisitsListFiltering( $this->params->dateRange, $this->params->excludeBots, $this->apiKey, @@ -67,7 +63,6 @@ class NonOrphanVisitsPaginatorAdapterTest extends TestCase $result = $this->adapter->getSlice($offset, $limit); self::assertEquals($list, $result); - $repoFind->shouldHaveBeenCalledOnce(); } public function provideLimitAndOffset(): iterable diff --git a/module/Core/test/Visit/Paginator/Adapter/OrphanVisitsPaginatorAdapterTest.php b/module/Core/test/Visit/Paginator/Adapter/OrphanVisitsPaginatorAdapterTest.php index 9e85b5fa..adad4322 100644 --- a/module/Core/test/Visit/Paginator/Adapter/OrphanVisitsPaginatorAdapterTest.php +++ b/module/Core/test/Visit/Paginator/Adapter/OrphanVisitsPaginatorAdapterTest.php @@ -4,9 +4,8 @@ declare(strict_types=1); namespace ShlinkioTest\Shlink\Core\Visit\Paginator\Adapter; +use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; -use Prophecy\PhpUnit\ProphecyTrait; -use Prophecy\Prophecy\ObjectProphecy; use Shlinkio\Shlink\Core\Visit\Entity\Visit; use Shlinkio\Shlink\Core\Visit\Model\Visitor; use Shlinkio\Shlink\Core\Visit\Model\VisitsParams; @@ -17,31 +16,28 @@ use Shlinkio\Shlink\Core\Visit\Repository\VisitRepositoryInterface; class OrphanVisitsPaginatorAdapterTest extends TestCase { - use ProphecyTrait; - private OrphanVisitsPaginatorAdapter $adapter; - private ObjectProphecy $repo; + private MockObject $repo; private VisitsParams $params; protected function setUp(): void { - $this->repo = $this->prophesize(VisitRepositoryInterface::class); + $this->repo = $this->createMock(VisitRepositoryInterface::class); $this->params = VisitsParams::fromRawData([]); - $this->adapter = new OrphanVisitsPaginatorAdapter($this->repo->reveal(), $this->params); + $this->adapter = new OrphanVisitsPaginatorAdapter($this->repo, $this->params); } /** @test */ public function countDelegatesToRepository(): void { $expectedCount = 5; - $repoCount = $this->repo->countOrphanVisits( + $this->repo->expects($this->once())->method('countOrphanVisits')->with( new VisitsCountFiltering($this->params->dateRange), )->willReturn($expectedCount); $result = $this->adapter->getNbResults(); self::assertEquals($expectedCount, $result); - $repoCount->shouldHaveBeenCalledOnce(); } /** @@ -52,14 +48,13 @@ class OrphanVisitsPaginatorAdapterTest extends TestCase { $visitor = Visitor::emptyInstance(); $list = [Visit::forRegularNotFound($visitor), Visit::forInvalidShortUrl($visitor)]; - $repoFind = $this->repo->findOrphanVisits( + $this->repo->expects($this->once())->method('findOrphanVisits')->with( new VisitsListFiltering($this->params->dateRange, $this->params->excludeBots, null, $limit, $offset), )->willReturn($list); $result = $this->adapter->getSlice($offset, $limit); self::assertEquals($list, $result); - $repoFind->shouldHaveBeenCalledOnce(); } public function provideLimitAndOffset(): iterable diff --git a/module/Core/test/Visit/Paginator/Adapter/ShortUrlVisitsPaginatorAdapterTest.php b/module/Core/test/Visit/Paginator/Adapter/ShortUrlVisitsPaginatorAdapterTest.php index 91f2fc32..3e6c3737 100644 --- a/module/Core/test/Visit/Paginator/Adapter/ShortUrlVisitsPaginatorAdapterTest.php +++ b/module/Core/test/Visit/Paginator/Adapter/ShortUrlVisitsPaginatorAdapterTest.php @@ -4,9 +4,8 @@ declare(strict_types=1); namespace ShlinkioTest\Shlink\Core\Visit\Paginator\Adapter; +use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; -use Prophecy\PhpUnit\ProphecyTrait; -use Prophecy\Prophecy\ObjectProphecy; use Shlinkio\Shlink\Common\Util\DateRange; use Shlinkio\Shlink\Core\ShortUrl\Model\ShortUrlIdentifier; use Shlinkio\Shlink\Core\Visit\Model\VisitsParams; @@ -18,13 +17,11 @@ use Shlinkio\Shlink\Rest\Entity\ApiKey; class ShortUrlVisitsPaginatorAdapterTest extends TestCase { - use ProphecyTrait; - - private ObjectProphecy $repo; + private MockObject $repo; protected function setUp(): void { - $this->repo = $this->prophesize(VisitRepositoryInterface::class); + $this->repo = $this->createMock(VisitRepositoryInterface::class); } /** @test */ @@ -34,7 +31,7 @@ class ShortUrlVisitsPaginatorAdapterTest extends TestCase $limit = 1; $offset = 5; $adapter = $this->createAdapter(null); - $findVisits = $this->repo->findVisitsByShortCode( + $this->repo->expects($this->exactly($count))->method('findVisitsByShortCode')->with( ShortUrlIdentifier::fromShortCodeAndDomain(''), new VisitsListFiltering(DateRange::allTime(), false, null, $limit, $offset), )->willReturn([]); @@ -42,8 +39,6 @@ class ShortUrlVisitsPaginatorAdapterTest extends TestCase for ($i = 0; $i < $count; $i++) { $adapter->getSlice($offset, $limit); } - - $findVisits->shouldHaveBeenCalledTimes($count); } /** @test */ @@ -52,7 +47,7 @@ class ShortUrlVisitsPaginatorAdapterTest extends TestCase $count = 3; $apiKey = ApiKey::create(); $adapter = $this->createAdapter($apiKey); - $countVisits = $this->repo->countVisitsByShortCode( + $this->repo->expects($this->once())->method('countVisitsByShortCode')->with( ShortUrlIdentifier::fromShortCodeAndDomain(''), new VisitsCountFiltering(DateRange::allTime(), false, $apiKey), )->willReturn(3); @@ -60,14 +55,12 @@ class ShortUrlVisitsPaginatorAdapterTest extends TestCase for ($i = 0; $i < $count; $i++) { $adapter->getNbResults(); } - - $countVisits->shouldHaveBeenCalledOnce(); } private function createAdapter(?ApiKey $apiKey): ShortUrlVisitsPaginatorAdapter { return new ShortUrlVisitsPaginatorAdapter( - $this->repo->reveal(), + $this->repo, ShortUrlIdentifier::fromShortCodeAndDomain(''), VisitsParams::fromRawData([]), $apiKey, diff --git a/module/Core/test/Visit/Paginator/Adapter/VisitsForTagPaginatorAdapterTest.php b/module/Core/test/Visit/Paginator/Adapter/VisitsForTagPaginatorAdapterTest.php index 59743637..3a92c8d3 100644 --- a/module/Core/test/Visit/Paginator/Adapter/VisitsForTagPaginatorAdapterTest.php +++ b/module/Core/test/Visit/Paginator/Adapter/VisitsForTagPaginatorAdapterTest.php @@ -4,9 +4,8 @@ declare(strict_types=1); namespace ShlinkioTest\Shlink\Core\Visit\Paginator\Adapter; +use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; -use Prophecy\PhpUnit\ProphecyTrait; -use Prophecy\Prophecy\ObjectProphecy; use Shlinkio\Shlink\Common\Util\DateRange; use Shlinkio\Shlink\Core\Visit\Model\VisitsParams; use Shlinkio\Shlink\Core\Visit\Paginator\Adapter\TagVisitsPaginatorAdapter; @@ -17,13 +16,11 @@ use Shlinkio\Shlink\Rest\Entity\ApiKey; class VisitsForTagPaginatorAdapterTest extends TestCase { - use ProphecyTrait; - - private ObjectProphecy $repo; + private MockObject $repo; protected function setUp(): void { - $this->repo = $this->prophesize(VisitRepositoryInterface::class); + $this->repo = $this->createMock(VisitRepositoryInterface::class); } /** @test */ @@ -33,7 +30,7 @@ class VisitsForTagPaginatorAdapterTest extends TestCase $limit = 1; $offset = 5; $adapter = $this->createAdapter(null); - $findVisits = $this->repo->findVisitsByTag( + $this->repo->expects($this->exactly($count))->method('findVisitsByTag')->with( 'foo', new VisitsListFiltering(DateRange::allTime(), false, null, $limit, $offset), )->willReturn([]); @@ -41,8 +38,6 @@ class VisitsForTagPaginatorAdapterTest extends TestCase for ($i = 0; $i < $count; $i++) { $adapter->getSlice($offset, $limit); } - - $findVisits->shouldHaveBeenCalledTimes($count); } /** @test */ @@ -51,7 +46,7 @@ class VisitsForTagPaginatorAdapterTest extends TestCase $count = 3; $apiKey = ApiKey::create(); $adapter = $this->createAdapter($apiKey); - $countVisits = $this->repo->countVisitsByTag( + $this->repo->expects($this->once())->method('countVisitsByTag')->with( 'foo', new VisitsCountFiltering(DateRange::allTime(), false, $apiKey), )->willReturn(3); @@ -59,17 +54,10 @@ class VisitsForTagPaginatorAdapterTest extends TestCase for ($i = 0; $i < $count; $i++) { $adapter->getNbResults(); } - - $countVisits->shouldHaveBeenCalledOnce(); } private function createAdapter(?ApiKey $apiKey): TagVisitsPaginatorAdapter { - return new TagVisitsPaginatorAdapter( - $this->repo->reveal(), - 'foo', - VisitsParams::fromRawData([]), - $apiKey, - ); + return new TagVisitsPaginatorAdapter($this->repo, 'foo', VisitsParams::fromRawData([]), $apiKey); } } diff --git a/module/Core/test/Visit/RequestTrackerTest.php b/module/Core/test/Visit/RequestTrackerTest.php index 81b70151..495963fb 100644 --- a/module/Core/test/Visit/RequestTrackerTest.php +++ b/module/Core/test/Visit/RequestTrackerTest.php @@ -7,10 +7,8 @@ namespace ShlinkioTest\Shlink\Core\Visit; use Fig\Http\Message\RequestMethodInterface; use Laminas\Diactoros\ServerRequestFactory; use Mezzio\Router\Middleware\ImplicitHeadMiddleware; +use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; -use Prophecy\Argument; -use Prophecy\PhpUnit\ProphecyTrait; -use Prophecy\Prophecy\ObjectProphecy; use Psr\Http\Message\ServerRequestInterface; use Shlinkio\Shlink\Common\Middleware\IpAddressMiddlewareFactory; use Shlinkio\Shlink\Core\ErrorHandler\Model\NotFoundType; @@ -22,31 +20,28 @@ use Shlinkio\Shlink\Core\Visit\VisitsTrackerInterface; class RequestTrackerTest extends TestCase { - use ProphecyTrait; - private const LONG_URL = 'https://domain.com/foo/bar?some=thing'; private RequestTracker $requestTracker; - private ObjectProphecy $visitsTracker; - private ObjectProphecy $notFoundType; + private MockObject $notFoundType; + private MockObject $visitsTracker; private ServerRequestInterface $request; protected function setUp(): void { - $this->notFoundType = $this->prophesize(NotFoundType::class); - $this->visitsTracker = $this->prophesize(VisitsTrackerInterface::class); - + $this->visitsTracker = $this->createMock(VisitsTrackerInterface::class); $this->requestTracker = new RequestTracker( - $this->visitsTracker->reveal(), + $this->visitsTracker, new TrackingOptions( disableTrackParam: 'foobar', disableTrackingFrom: ['80.90.100.110', '192.168.10.0/24', '1.2.*.*'], ), ); + $this->notFoundType = $this->createMock(NotFoundType::class); $this->request = ServerRequestFactory::fromGlobals()->withAttribute( NotFoundType::class, - $this->notFoundType->reveal(), + $this->notFoundType, ); } @@ -56,11 +51,10 @@ class RequestTrackerTest extends TestCase */ public function trackingIsDisabledWhenRequestDoesNotMeetConditions(ServerRequestInterface $request): void { + $this->visitsTracker->expects($this->never())->method('track'); + $shortUrl = ShortUrl::withLongUrl(self::LONG_URL); - $this->requestTracker->trackIfApplicable($shortUrl, $request); - - $this->visitsTracker->track(Argument::cetera())->shouldNotHaveBeenCalled(); } public function provideNonTrackingRequests(): iterable @@ -91,61 +85,57 @@ class RequestTrackerTest extends TestCase public function trackingHappensOverShortUrlsWhenRequestMeetsConditions(): void { $shortUrl = ShortUrl::withLongUrl(self::LONG_URL); + $this->visitsTracker->expects($this->once())->method('track')->with( + $shortUrl, + $this->isInstanceOf(Visitor::class), + ); $this->requestTracker->trackIfApplicable($shortUrl, $this->request); - - $this->visitsTracker->track($shortUrl, Argument::type(Visitor::class))->shouldHaveBeenCalledOnce(); } /** @test */ public function baseUrlErrorIsTracked(): void { - $isBaseUrl = $this->notFoundType->isBaseUrl()->willReturn(true); - $isRegularNotFound = $this->notFoundType->isRegularNotFound()->willReturn(false); - $isInvalidShortUrl = $this->notFoundType->isInvalidShortUrl()->willReturn(false); + $this->notFoundType->expects($this->once())->method('isBaseUrl')->willReturn(true); + $this->notFoundType->expects($this->never())->method('isRegularNotFound'); + $this->notFoundType->expects($this->never())->method('isInvalidShortUrl'); + $this->visitsTracker->expects($this->once())->method('trackBaseUrlVisit')->with( + $this->isInstanceOf(Visitor::class), + ); + $this->visitsTracker->expects($this->never())->method('trackRegularNotFoundVisit'); + $this->visitsTracker->expects($this->never())->method('trackInvalidShortUrlVisit'); $this->requestTracker->trackNotFoundIfApplicable($this->request); - - $isBaseUrl->shouldHaveBeenCalledOnce(); - $isRegularNotFound->shouldNotHaveBeenCalled(); - $isInvalidShortUrl->shouldNotHaveBeenCalled(); - $this->visitsTracker->trackBaseUrlVisit(Argument::type(Visitor::class))->shouldHaveBeenCalledOnce(); - $this->visitsTracker->trackRegularNotFoundVisit(Argument::type(Visitor::class))->shouldNotHaveBeenCalled(); - $this->visitsTracker->trackInvalidShortUrlVisit(Argument::type(Visitor::class))->shouldNotHaveBeenCalled(); } /** @test */ public function regularNotFoundErrorIsTracked(): void { - $isBaseUrl = $this->notFoundType->isBaseUrl()->willReturn(false); - $isRegularNotFound = $this->notFoundType->isRegularNotFound()->willReturn(true); - $isInvalidShortUrl = $this->notFoundType->isInvalidShortUrl()->willReturn(false); + $this->notFoundType->expects($this->once())->method('isBaseUrl')->willReturn(false); + $this->notFoundType->expects($this->once())->method('isRegularNotFound')->willReturn(true); + $this->notFoundType->expects($this->never())->method('isInvalidShortUrl'); + $this->visitsTracker->expects($this->never())->method('trackBaseUrlVisit'); + $this->visitsTracker->expects($this->once())->method('trackRegularNotFoundVisit')->with( + $this->isInstanceOf(Visitor::class), + ); + $this->visitsTracker->expects($this->never())->method('trackInvalidShortUrlVisit'); $this->requestTracker->trackNotFoundIfApplicable($this->request); - - $isBaseUrl->shouldHaveBeenCalledOnce(); - $isRegularNotFound->shouldHaveBeenCalledOnce(); - $isInvalidShortUrl->shouldNotHaveBeenCalled(); - $this->visitsTracker->trackBaseUrlVisit(Argument::type(Visitor::class))->shouldNotHaveBeenCalled(); - $this->visitsTracker->trackRegularNotFoundVisit(Argument::type(Visitor::class))->shouldHaveBeenCalledOnce(); - $this->visitsTracker->trackInvalidShortUrlVisit(Argument::type(Visitor::class))->shouldNotHaveBeenCalled(); } /** @test */ public function invalidShortUrlErrorIsTracked(): void { - $isBaseUrl = $this->notFoundType->isBaseUrl()->willReturn(false); - $isRegularNotFound = $this->notFoundType->isRegularNotFound()->willReturn(false); - $isInvalidShortUrl = $this->notFoundType->isInvalidShortUrl()->willReturn(true); + $this->notFoundType->expects($this->once())->method('isBaseUrl')->willReturn(false); + $this->notFoundType->expects($this->once())->method('isRegularNotFound')->willReturn(false); + $this->notFoundType->expects($this->once())->method('isInvalidShortUrl')->willReturn(true); + $this->visitsTracker->expects($this->never())->method('trackBaseUrlVisit'); + $this->visitsTracker->expects($this->never())->method('trackRegularNotFoundVisit'); + $this->visitsTracker->expects($this->once())->method('trackInvalidShortUrlVisit')->with( + $this->isInstanceOf(Visitor::class), + ); $this->requestTracker->trackNotFoundIfApplicable($this->request); - - $isBaseUrl->shouldHaveBeenCalledOnce(); - $isRegularNotFound->shouldHaveBeenCalledOnce(); - $isInvalidShortUrl->shouldHaveBeenCalledOnce(); - $this->visitsTracker->trackBaseUrlVisit(Argument::type(Visitor::class))->shouldNotHaveBeenCalled(); - $this->visitsTracker->trackRegularNotFoundVisit(Argument::type(Visitor::class))->shouldNotHaveBeenCalled(); - $this->visitsTracker->trackInvalidShortUrlVisit(Argument::type(Visitor::class))->shouldHaveBeenCalledOnce(); } /** @@ -154,10 +144,10 @@ class RequestTrackerTest extends TestCase */ public function notFoundIsNotTrackedIfRequestDoesNotMeetConditions(ServerRequestInterface $request): void { - $this->requestTracker->trackNotFoundIfApplicable($request); + $this->visitsTracker->expects($this->never())->method('trackBaseUrlVisit'); + $this->visitsTracker->expects($this->never())->method('trackRegularNotFoundVisit'); + $this->visitsTracker->expects($this->never())->method('trackInvalidShortUrlVisit'); - $this->visitsTracker->trackBaseUrlVisit(Argument::cetera())->shouldNotHaveBeenCalled(); - $this->visitsTracker->trackRegularNotFoundVisit(Argument::cetera())->shouldNotHaveBeenCalled(); - $this->visitsTracker->trackInvalidShortUrlVisit(Argument::cetera())->shouldNotHaveBeenCalled(); + $this->requestTracker->trackNotFoundIfApplicable($request); } } diff --git a/module/Core/test/Visit/VisitsStatsHelperTest.php b/module/Core/test/Visit/VisitsStatsHelperTest.php index c255dd6a..4f3ffee2 100644 --- a/module/Core/test/Visit/VisitsStatsHelperTest.php +++ b/module/Core/test/Visit/VisitsStatsHelperTest.php @@ -6,10 +6,8 @@ namespace ShlinkioTest\Shlink\Core\Visit; use Doctrine\ORM\EntityManagerInterface; use Laminas\Stdlib\ArrayUtils; +use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; -use Prophecy\Argument; -use Prophecy\PhpUnit\ProphecyTrait; -use Prophecy\Prophecy\ObjectProphecy; use Shlinkio\Shlink\Core\Domain\Entity\Domain; use Shlinkio\Shlink\Core\Domain\Repository\DomainRepository; use Shlinkio\Shlink\Core\Exception\DomainNotFoundException; @@ -38,15 +36,14 @@ use function range; class VisitsStatsHelperTest extends TestCase { use ApiKeyHelpersTrait; - use ProphecyTrait; private VisitsStatsHelper $helper; - private ObjectProphecy $em; + private MockObject $em; protected function setUp(): void { - $this->em = $this->prophesize(EntityManagerInterface::class); - $this->helper = new VisitsStatsHelper($this->em->reveal()); + $this->em = $this->createMock(EntityManagerInterface::class); + $this->helper = new VisitsStatsHelper($this->em); } /** @@ -55,19 +52,18 @@ class VisitsStatsHelperTest extends TestCase */ public function returnsExpectedVisitsStats(int $expectedCount): void { - $repo = $this->prophesize(VisitRepository::class); - $count = $repo->countNonOrphanVisits(new VisitsCountFiltering())->willReturn($expectedCount * 3); - $countOrphan = $repo->countOrphanVisits(Argument::type(VisitsCountFiltering::class))->willReturn( - $expectedCount, + $repo = $this->createMock(VisitRepository::class); + $repo->expects($this->once())->method('countNonOrphanVisits')->with(new VisitsCountFiltering())->willReturn( + $expectedCount * 3, ); - $getRepo = $this->em->getRepository(Visit::class)->willReturn($repo->reveal()); + $repo->expects($this->once())->method('countOrphanVisits')->with( + $this->isInstanceOf(VisitsCountFiltering::class), + )->willReturn($expectedCount); + $this->em->expects($this->once())->method('getRepository')->with(Visit::class)->willReturn($repo); $stats = $this->helper->getVisitsStats(); self::assertEquals(new VisitsStats($expectedCount * 3, $expectedCount), $stats); - $count->shouldHaveBeenCalledOnce(); - $countOrphan->shouldHaveBeenCalledOnce(); - $getRepo->shouldHaveBeenCalledOnce(); } public function provideCounts(): iterable @@ -85,22 +81,28 @@ class VisitsStatsHelperTest extends TestCase $identifier = ShortUrlIdentifier::fromShortCodeAndDomain($shortCode); $spec = $apiKey?->spec(); - $repo = $this->prophesize(ShortUrlRepositoryInterface::class); - $count = $repo->shortCodeIsInUse($identifier, $spec)->willReturn( - true, - ); - $this->em->getRepository(ShortUrl::class)->willReturn($repo->reveal())->shouldBeCalledOnce(); + $repo = $this->createMock(ShortUrlRepositoryInterface::class); + $repo->expects($this->once())->method('shortCodeIsInUse')->with($identifier, $spec)->willReturn(true); $list = map(range(0, 1), fn () => Visit::forValidShortUrl(ShortUrl::createEmpty(), Visitor::emptyInstance())); - $repo2 = $this->prophesize(VisitRepository::class); - $repo2->findVisitsByShortCode($identifier, Argument::type(VisitsListFiltering::class))->willReturn($list); - $repo2->countVisitsByShortCode($identifier, Argument::type(VisitsCountFiltering::class))->willReturn(1); - $this->em->getRepository(Visit::class)->willReturn($repo2->reveal())->shouldBeCalledOnce(); + $repo2 = $this->createMock(VisitRepository::class); + $repo2->method('findVisitsByShortCode')->with( + $identifier, + $this->isInstanceOf(VisitsListFiltering::class), + )->willReturn($list); + $repo2->method('countVisitsByShortCode')->with( + $identifier, + $this->isInstanceOf(VisitsCountFiltering::class), + )->willReturn(1); + + $this->em->expects($this->exactly(2))->method('getRepository')->willReturnMap([ + [ShortUrl::class, $repo], + [Visit::class, $repo2], + ]); $paginator = $this->helper->visitsForShortUrl($identifier, new VisitsParams(), $apiKey); self::assertEquals($list, ArrayUtils::iteratorToArray($paginator->getCurrentPageResults())); - $count->shouldHaveBeenCalledOnce(); } /** @test */ @@ -109,14 +111,11 @@ class VisitsStatsHelperTest extends TestCase $shortCode = '123ABC'; $identifier = ShortUrlIdentifier::fromShortCodeAndDomain($shortCode); - $repo = $this->prophesize(ShortUrlRepositoryInterface::class); - $count = $repo->shortCodeIsInUse($identifier, null)->willReturn( - false, - ); - $this->em->getRepository(ShortUrl::class)->willReturn($repo->reveal())->shouldBeCalledOnce(); + $repo = $this->createMock(ShortUrlRepositoryInterface::class); + $repo->expects($this->once())->method('shortCodeIsInUse')->with($identifier, null)->willReturn(false); + $this->em->expects($this->once())->method('getRepository')->with(ShortUrl::class)->willReturn($repo); $this->expectException(ShortUrlNotFoundException::class); - $count->shouldBeCalledOnce(); $this->helper->visitsForShortUrl($identifier, new VisitsParams()); } @@ -126,13 +125,11 @@ class VisitsStatsHelperTest extends TestCase { $tag = 'foo'; $apiKey = ApiKey::create(); - $repo = $this->prophesize(TagRepository::class); - $tagExists = $repo->tagExists($tag, $apiKey)->willReturn(false); - $getRepo = $this->em->getRepository(Tag::class)->willReturn($repo->reveal()); + $repo = $this->createMock(TagRepository::class); + $repo->expects($this->once())->method('tagExists')->with($tag, $apiKey)->willReturn(false); + $this->em->expects($this->once())->method('getRepository')->with(Tag::class)->willReturn($repo); $this->expectException(TagNotFoundException::class); - $tagExists->shouldBeCalledOnce(); - $getRepo->shouldBeCalledOnce(); $this->helper->visitsForTag($tag, new VisitsParams(), $apiKey); } @@ -144,21 +141,24 @@ class VisitsStatsHelperTest extends TestCase public function visitsForTagAreReturnedAsExpected(?ApiKey $apiKey): void { $tag = 'foo'; - $repo = $this->prophesize(TagRepository::class); - $tagExists = $repo->tagExists($tag, $apiKey)->willReturn(true); - $getRepo = $this->em->getRepository(Tag::class)->willReturn($repo->reveal()); + $repo = $this->createMock(TagRepository::class); + $repo->expects($this->once())->method('tagExists')->with($tag, $apiKey)->willReturn(true); $list = map(range(0, 1), fn () => Visit::forValidShortUrl(ShortUrl::createEmpty(), Visitor::emptyInstance())); - $repo2 = $this->prophesize(VisitRepository::class); - $repo2->findVisitsByTag($tag, Argument::type(VisitsListFiltering::class))->willReturn($list); - $repo2->countVisitsByTag($tag, Argument::type(VisitsCountFiltering::class))->willReturn(1); - $this->em->getRepository(Visit::class)->willReturn($repo2->reveal())->shouldBeCalledOnce(); + $repo2 = $this->createMock(VisitRepository::class); + $repo2->method('findVisitsByTag')->with($tag, $this->isInstanceOf(VisitsListFiltering::class))->willReturn( + $list, + ); + $repo2->method('countVisitsByTag')->with($tag, $this->isInstanceOf(VisitsCountFiltering::class))->willReturn(1); + + $this->em->expects($this->exactly(2))->method('getRepository')->willReturnMap([ + [Tag::class, $repo], + [Visit::class, $repo2], + ]); $paginator = $this->helper->visitsForTag($tag, new VisitsParams(), $apiKey); self::assertEquals($list, ArrayUtils::iteratorToArray($paginator->getCurrentPageResults())); - $tagExists->shouldHaveBeenCalledOnce(); - $getRepo->shouldHaveBeenCalledOnce(); } /** @test */ @@ -166,13 +166,11 @@ class VisitsStatsHelperTest extends TestCase { $domain = 'foo.com'; $apiKey = ApiKey::create(); - $repo = $this->prophesize(DomainRepository::class); - $domainExists = $repo->domainExists($domain, $apiKey)->willReturn(false); - $getRepo = $this->em->getRepository(Domain::class)->willReturn($repo->reveal()); + $repo = $this->createMock(DomainRepository::class); + $repo->expects($this->once())->method('domainExists')->with($domain, $apiKey)->willReturn(false); + $this->em->expects($this->once())->method('getRepository')->with(Domain::class)->willReturn($repo); $this->expectException(DomainNotFoundException::class); - $domainExists->shouldBeCalledOnce(); - $getRepo->shouldBeCalledOnce(); $this->helper->visitsForDomain($domain, new VisitsParams(), $apiKey); } @@ -184,21 +182,28 @@ class VisitsStatsHelperTest extends TestCase public function visitsForNonDefaultDomainAreReturnedAsExpected(?ApiKey $apiKey): void { $domain = 'foo.com'; - $repo = $this->prophesize(DomainRepository::class); - $domainExists = $repo->domainExists($domain, $apiKey)->willReturn(true); - $getRepo = $this->em->getRepository(Domain::class)->willReturn($repo->reveal()); + $repo = $this->createMock(DomainRepository::class); + $repo->expects($this->once())->method('domainExists')->with($domain, $apiKey)->willReturn(true); $list = map(range(0, 1), fn () => Visit::forValidShortUrl(ShortUrl::createEmpty(), Visitor::emptyInstance())); - $repo2 = $this->prophesize(VisitRepository::class); - $repo2->findVisitsByDomain($domain, Argument::type(VisitsListFiltering::class))->willReturn($list); - $repo2->countVisitsByDomain($domain, Argument::type(VisitsCountFiltering::class))->willReturn(1); - $this->em->getRepository(Visit::class)->willReturn($repo2->reveal())->shouldBeCalledOnce(); + $repo2 = $this->createMock(VisitRepository::class); + $repo2->method('findVisitsByDomain')->with( + $domain, + $this->isInstanceOf(VisitsListFiltering::class), + )->willReturn($list); + $repo2->method('countVisitsByDomain')->with( + $domain, + $this->isInstanceOf(VisitsCountFiltering::class), + )->willReturn(1); + + $this->em->expects($this->exactly(2))->method('getRepository')->willReturnMap([ + [Domain::class, $repo], + [Visit::class, $repo2], + ]); $paginator = $this->helper->visitsForDomain($domain, new VisitsParams(), $apiKey); self::assertEquals($list, ArrayUtils::iteratorToArray($paginator->getCurrentPageResults())); - $domainExists->shouldHaveBeenCalledOnce(); - $getRepo->shouldHaveBeenCalledOnce(); } /** @@ -207,56 +212,63 @@ class VisitsStatsHelperTest extends TestCase */ public function visitsForDefaultDomainAreReturnedAsExpected(?ApiKey $apiKey): void { - $repo = $this->prophesize(DomainRepository::class); - $domainExists = $repo->domainExists(Argument::cetera()); - $getRepo = $this->em->getRepository(Domain::class)->willReturn($repo->reveal()); + $repo = $this->createMock(DomainRepository::class); + $repo->expects($this->never())->method('domainExists'); $list = map(range(0, 1), fn () => Visit::forValidShortUrl(ShortUrl::createEmpty(), Visitor::emptyInstance())); - $repo2 = $this->prophesize(VisitRepository::class); - $repo2->findVisitsByDomain('DEFAULT', Argument::type(VisitsListFiltering::class))->willReturn($list); - $repo2->countVisitsByDomain('DEFAULT', Argument::type(VisitsCountFiltering::class))->willReturn(1); - $this->em->getRepository(Visit::class)->willReturn($repo2->reveal())->shouldBeCalledOnce(); + $repo2 = $this->createMock(VisitRepository::class); + $repo2->method('findVisitsByDomain')->with( + 'DEFAULT', + $this->isInstanceOf(VisitsListFiltering::class), + )->willReturn($list); + $repo2->method('countVisitsByDomain')->with( + 'DEFAULT', + $this->isInstanceOf(VisitsCountFiltering::class), + )->willReturn(1); + + $this->em->expects($this->exactly(2))->method('getRepository')->willReturnMap([ + [Domain::class, $repo], + [Visit::class, $repo2], + ]); $paginator = $this->helper->visitsForDomain('DEFAULT', new VisitsParams(), $apiKey); self::assertEquals($list, ArrayUtils::iteratorToArray($paginator->getCurrentPageResults())); - $domainExists->shouldNotHaveBeenCalled(); - $getRepo->shouldHaveBeenCalledOnce(); } /** @test */ public function orphanVisitsAreReturnedAsExpected(): void { $list = map(range(0, 3), fn () => Visit::forBasePath(Visitor::emptyInstance())); - $repo = $this->prophesize(VisitRepository::class); - $countVisits = $repo->countOrphanVisits(Argument::type(VisitsCountFiltering::class))->willReturn(count($list)); - $listVisits = $repo->findOrphanVisits(Argument::type(VisitsListFiltering::class))->willReturn($list); - $getRepo = $this->em->getRepository(Visit::class)->willReturn($repo->reveal()); + $repo = $this->createMock(VisitRepository::class); + $repo->expects($this->once())->method('countOrphanVisits')->with( + $this->isInstanceOf(VisitsCountFiltering::class), + )->willReturn(count($list)); + $repo->expects($this->once())->method('findOrphanVisits')->with( + $this->isInstanceOf(VisitsListFiltering::class), + )->willReturn($list); + $this->em->expects($this->once())->method('getRepository')->with(Visit::class)->willReturn($repo); $paginator = $this->helper->orphanVisits(new VisitsParams()); self::assertEquals($list, ArrayUtils::iteratorToArray($paginator->getCurrentPageResults())); - $listVisits->shouldHaveBeenCalledOnce(); - $countVisits->shouldHaveBeenCalledOnce(); - $getRepo->shouldHaveBeenCalledOnce(); } /** @test */ public function nonOrphanVisitsAreReturnedAsExpected(): void { $list = map(range(0, 3), fn () => Visit::forValidShortUrl(ShortUrl::createEmpty(), Visitor::emptyInstance())); - $repo = $this->prophesize(VisitRepository::class); - $countVisits = $repo->countNonOrphanVisits(Argument::type(VisitsCountFiltering::class))->willReturn( - count($list), - ); - $listVisits = $repo->findNonOrphanVisits(Argument::type(VisitsListFiltering::class))->willReturn($list); - $getRepo = $this->em->getRepository(Visit::class)->willReturn($repo->reveal()); + $repo = $this->createMock(VisitRepository::class); + $repo->expects($this->once())->method('countNonOrphanVisits')->with( + $this->isInstanceOf(VisitsCountFiltering::class), + )->willReturn(count($list)); + $repo->expects($this->once())->method('findNonOrphanVisits')->with( + $this->isInstanceOf(VisitsListFiltering::class), + )->willReturn($list); + $this->em->expects($this->once())->method('getRepository')->with(Visit::class)->willReturn($repo); $paginator = $this->helper->nonOrphanVisits(new VisitsParams()); self::assertEquals($list, ArrayUtils::iteratorToArray($paginator->getCurrentPageResults())); - $listVisits->shouldHaveBeenCalledOnce(); - $countVisits->shouldHaveBeenCalledOnce(); - $getRepo->shouldHaveBeenCalledOnce(); } } diff --git a/module/Core/test/Visit/VisitsTrackerTest.php b/module/Core/test/Visit/VisitsTrackerTest.php index c10d57b1..abdf8fb3 100644 --- a/module/Core/test/Visit/VisitsTrackerTest.php +++ b/module/Core/test/Visit/VisitsTrackerTest.php @@ -5,10 +5,8 @@ declare(strict_types=1); namespace ShlinkioTest\Shlink\Core\Visit; use Doctrine\ORM\EntityManager; +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 Shlinkio\Shlink\Core\EventDispatcher\Event\UrlVisited; use Shlinkio\Shlink\Core\Options\TrackingOptions; @@ -19,16 +17,13 @@ use Shlinkio\Shlink\Core\Visit\VisitsTracker; class VisitsTrackerTest extends TestCase { - use ProphecyTrait; - - private VisitsTracker $visitsTracker; - private ObjectProphecy $em; - private ObjectProphecy $eventDispatcher; + private MockObject $em; + private MockObject $eventDispatcher; protected function setUp(): void { - $this->em = $this->prophesize(EntityManager::class); - $this->eventDispatcher = $this->prophesize(EventDispatcherInterface::class); + $this->em = $this->createMock(EntityManager::class); + $this->eventDispatcher = $this->createMock(EventDispatcherInterface::class); } /** @@ -37,14 +32,15 @@ class VisitsTrackerTest extends TestCase */ public function trackPersistsVisitAndDispatchesEvent(string $method, array $args): void { - $persist = $this->em->persist(Argument::that(fn (Visit $visit) => $visit->setId('1')))->will(function (): void { - }); + $this->em->expects($this->once())->method('persist')->with( + $this->callback(fn (Visit $visit) => $visit->setId('1') !== null), + ); + $this->em->expects($this->once())->method('flush'); + $this->eventDispatcher->expects($this->once())->method('dispatch')->with( + $this->isInstanceOf(UrlVisited::class), + ); $this->visitsTracker()->{$method}(...$args); - - $persist->shouldHaveBeenCalledOnce(); - $this->em->flush()->shouldHaveBeenCalledOnce(); - $this->eventDispatcher->dispatch(Argument::type(UrlVisited::class))->shouldHaveBeenCalled(); } /** @@ -53,11 +49,11 @@ class VisitsTrackerTest extends TestCase */ public function trackingIsSkippedCompletelyWhenDisabledFromOptions(string $method, array $args): void { - $this->visitsTracker(new TrackingOptions(disableTracking: true))->{$method}(...$args); + $this->em->expects($this->never())->method('persist'); + $this->em->expects($this->never())->method('flush'); + $this->eventDispatcher->expects($this->never())->method('dispatch'); - $this->eventDispatcher->dispatch(Argument::cetera())->shouldNotHaveBeenCalled(); - $this->em->persist(Argument::cetera())->shouldNotHaveBeenCalled(); - $this->em->flush()->shouldNotHaveBeenCalled(); + $this->visitsTracker(new TrackingOptions(disableTracking: true))->{$method}(...$args); } public function provideTrackingMethodNames(): iterable @@ -74,11 +70,11 @@ class VisitsTrackerTest extends TestCase */ public function orphanVisitsAreNotTrackedWhenDisabled(string $method): void { - $this->visitsTracker(new TrackingOptions(trackOrphanVisits: false))->{$method}(Visitor::emptyInstance()); + $this->em->expects($this->never())->method('persist'); + $this->em->expects($this->never())->method('flush'); + $this->eventDispatcher->expects($this->never())->method('dispatch'); - $this->eventDispatcher->dispatch(Argument::cetera())->shouldNotHaveBeenCalled(); - $this->em->persist(Argument::cetera())->shouldNotHaveBeenCalled(); - $this->em->flush()->shouldNotHaveBeenCalled(); + $this->visitsTracker(new TrackingOptions(trackOrphanVisits: false))->{$method}(Visitor::emptyInstance()); } public function provideOrphanTrackingMethodNames(): iterable @@ -90,10 +86,6 @@ class VisitsTrackerTest extends TestCase private function visitsTracker(?TrackingOptions $options = null): VisitsTracker { - return new VisitsTracker( - $this->em->reveal(), - $this->eventDispatcher->reveal(), - $options ?? new TrackingOptions(), - ); + return new VisitsTracker($this->em, $this->eventDispatcher, $options ?? new TrackingOptions()); } } diff --git a/module/Rest/test/Action/Domain/DomainRedirectsActionTest.php b/module/Rest/test/Action/Domain/DomainRedirectsActionTest.php index 19e34ccf..a620ee01 100644 --- a/module/Rest/test/Action/Domain/DomainRedirectsActionTest.php +++ b/module/Rest/test/Action/Domain/DomainRedirectsActionTest.php @@ -6,10 +6,8 @@ namespace ShlinkioTest\Shlink\Rest\Action\Domain; use Laminas\Diactoros\Response\JsonResponse; use Laminas\Diactoros\ServerRequestFactory; +use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; -use Prophecy\Argument; -use Prophecy\PhpUnit\ProphecyTrait; -use Prophecy\Prophecy\ObjectProphecy; use Shlinkio\Shlink\Core\Config\NotFoundRedirects; use Shlinkio\Shlink\Core\Domain\DomainServiceInterface; use Shlinkio\Shlink\Core\Domain\Entity\Domain; @@ -22,15 +20,13 @@ use function array_key_exists; class DomainRedirectsActionTest extends TestCase { - use ProphecyTrait; - private DomainRedirectsAction $action; - private ObjectProphecy $domainService; + private MockObject $domainService; protected function setUp(): void { - $this->domainService = $this->prophesize(DomainServiceInterface::class); - $this->action = new DomainRedirectsAction($this->domainService->reveal()); + $this->domainService = $this->createMock(DomainServiceInterface::class); + $this->action = new DomainRedirectsAction($this->domainService); } /** @@ -42,8 +38,8 @@ class DomainRedirectsActionTest extends TestCase $request = ServerRequestFactory::fromGlobals()->withParsedBody($body); $this->expectException(ValidationException::class); - $this->domainService->getOrCreate(Argument::cetera())->shouldNotBeCalled(); - $this->domainService->configureNotFoundRedirects(Argument::cetera())->shouldNotBeCalled(); + $this->domainService->expects($this->never())->method('getOrCreate'); + $this->domainService->expects($this->never())->method('configureNotFoundRedirects'); $this->action->handle($request); } @@ -70,19 +66,19 @@ class DomainRedirectsActionTest extends TestCase $request = ServerRequestFactory::fromGlobals()->withParsedBody($redirects) ->withAttribute(ApiKey::class, $apiKey); - $getOrCreate = $this->domainService->getOrCreate($authority)->willReturn($domain); - $configureNotFoundRedirects = $this->domainService->configureNotFoundRedirects( + $this->domainService->expects($this->once())->method('getOrCreate')->with($authority)->willReturn($domain); + $this->domainService->expects($this->once())->method('configureNotFoundRedirects')->with( $authority, NotFoundRedirects::withRedirects( array_key_exists(DomainRedirectsInputFilter::BASE_URL_REDIRECT, $redirects) ? $redirects[DomainRedirectsInputFilter::BASE_URL_REDIRECT] - : $domain?->baseUrlRedirect(), + : $domain->baseUrlRedirect(), array_key_exists(DomainRedirectsInputFilter::REGULAR_404_REDIRECT, $redirects) ? $redirects[DomainRedirectsInputFilter::REGULAR_404_REDIRECT] - : $domain?->regular404Redirect(), + : $domain->regular404Redirect(), array_key_exists(DomainRedirectsInputFilter::INVALID_SHORT_URL_REDIRECT, $redirects) ? $redirects[DomainRedirectsInputFilter::INVALID_SHORT_URL_REDIRECT] - : $domain?->invalidShortUrlRedirect(), + : $domain->invalidShortUrlRedirect(), ), $apiKey, ); @@ -93,8 +89,6 @@ class DomainRedirectsActionTest extends TestCase $payload = $response->getPayload(); self::assertEquals($expectedResult, $payload->jsonSerialize()); - $getOrCreate->shouldHaveBeenCalledOnce(); - $configureNotFoundRedirects->shouldHaveBeenCalledOnce(); } public function provideDomainsAndRedirects(): iterable diff --git a/module/Rest/test/Action/Domain/ListDomainsActionTest.php b/module/Rest/test/Action/Domain/ListDomainsActionTest.php index b04c8d0e..8c7fcc94 100644 --- a/module/Rest/test/Action/Domain/ListDomainsActionTest.php +++ b/module/Rest/test/Action/Domain/ListDomainsActionTest.php @@ -6,9 +6,8 @@ namespace ShlinkioTest\Shlink\Rest\Action\Domain; use Laminas\Diactoros\Response\JsonResponse; use Laminas\Diactoros\ServerRequestFactory; +use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; -use Prophecy\PhpUnit\ProphecyTrait; -use Prophecy\Prophecy\ObjectProphecy; use Shlinkio\Shlink\Core\Config\NotFoundRedirects; use Shlinkio\Shlink\Core\Domain\DomainServiceInterface; use Shlinkio\Shlink\Core\Domain\Entity\Domain; @@ -19,17 +18,15 @@ use Shlinkio\Shlink\Rest\Entity\ApiKey; class ListDomainsActionTest extends TestCase { - use ProphecyTrait; - private ListDomainsAction $action; - private ObjectProphecy $domainService; + private MockObject $domainService; private NotFoundRedirectOptions $options; protected function setUp(): void { - $this->domainService = $this->prophesize(DomainServiceInterface::class); + $this->domainService = $this->createMock(DomainServiceInterface::class); $this->options = new NotFoundRedirectOptions(); - $this->action = new ListDomainsAction($this->domainService->reveal(), $this->options); + $this->action = new ListDomainsAction($this->domainService, $this->options); } /** @test */ @@ -40,7 +37,7 @@ class ListDomainsActionTest extends TestCase DomainItem::forDefaultDomain('bar.com', new NotFoundRedirectOptions()), DomainItem::forNonDefaultDomain(Domain::withAuthority('baz.com')), ]; - $listDomains = $this->domainService->listDomains($apiKey)->willReturn($domains); + $this->domainService->expects($this->once())->method('listDomains')->with($apiKey)->willReturn($domains); /** @var JsonResponse $resp */ $resp = $this->action->handle(ServerRequestFactory::fromGlobals()->withAttribute(ApiKey::class, $apiKey)); @@ -52,6 +49,5 @@ class ListDomainsActionTest extends TestCase 'defaultRedirects' => NotFoundRedirects::fromConfig($this->options), ], ], $payload); - $listDomains->shouldHaveBeenCalledOnce(); } } diff --git a/module/Rest/test/Action/HealthActionTest.php b/module/Rest/test/Action/HealthActionTest.php index 461152a4..48289290 100644 --- a/module/Rest/test/Action/HealthActionTest.php +++ b/module/Rest/test/Action/HealthActionTest.php @@ -11,37 +11,34 @@ use Doctrine\ORM\EntityManagerInterface; use Exception; use Laminas\Diactoros\Response\JsonResponse; use Laminas\Diactoros\ServerRequest; +use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; -use Prophecy\Argument; -use Prophecy\PhpUnit\ProphecyTrait; -use Prophecy\Prophecy\ObjectProphecy; use Shlinkio\Shlink\Core\Options\AppOptions; use Shlinkio\Shlink\Rest\Action\HealthAction; class HealthActionTest extends TestCase { - use ProphecyTrait; - private HealthAction $action; - private ObjectProphecy $conn; + private MockObject $conn; protected function setUp(): void { - $this->conn = $this->prophesize(Connection::class); - $this->conn->executeQuery(Argument::cetera())->willReturn($this->prophesize(Result::class)->reveal()); - $dbPlatform = $this->prophesize(AbstractPlatform::class); - $dbPlatform->getDummySelectSQL()->willReturn(''); - $this->conn->getDatabasePlatform()->willReturn($dbPlatform->reveal()); + $this->conn = $this->createMock(Connection::class); + $dbPlatform = $this->createMock(AbstractPlatform::class); + $dbPlatform->method('getDummySelectSQL')->willReturn(''); + $this->conn->method('getDatabasePlatform')->willReturn($dbPlatform); - $em = $this->prophesize(EntityManagerInterface::class); - $em->getConnection()->willReturn($this->conn->reveal()); + $em = $this->createMock(EntityManagerInterface::class); + $em->method('getConnection')->willReturn($this->conn); - $this->action = new HealthAction($em->reveal(), new AppOptions(version: '1.2.3')); + $this->action = new HealthAction($em, new AppOptions(version: '1.2.3')); } /** @test */ public function passResponseIsReturnedWhenDummyQuerySucceeds(): void { + $this->conn->expects($this->once())->method('executeQuery')->willReturn($this->createMock(Result::class)); + /** @var JsonResponse $resp */ $resp = $this->action->handle(new ServerRequest()); $payload = $resp->getPayload(); @@ -54,13 +51,12 @@ class HealthActionTest extends TestCase 'project' => 'https://github.com/shlinkio/shlink', ], $payload['links']); self::assertEquals('application/health+json', $resp->getHeaderLine('Content-type')); - $this->conn->executeQuery(Argument::cetera())->shouldHaveBeenCalledOnce(); } /** @test */ public function failResponseIsReturnedWhenDummyQueryThrowsException(): void { - $executeQuery = $this->conn->executeQuery(Argument::cetera())->willThrow(Exception::class); + $this->conn->expects($this->once())->method('executeQuery')->willThrowException(new Exception()); /** @var JsonResponse $resp */ $resp = $this->action->handle(new ServerRequest()); @@ -74,6 +70,5 @@ class HealthActionTest extends TestCase 'project' => 'https://github.com/shlinkio/shlink', ], $payload['links']); self::assertEquals('application/health+json', $resp->getHeaderLine('Content-type')); - $executeQuery->shouldHaveBeenCalledOnce(); } } diff --git a/module/Rest/test/Action/MercureInfoActionTest.php b/module/Rest/test/Action/MercureInfoActionTest.php index e586a641..f99a8a37 100644 --- a/module/Rest/test/Action/MercureInfoActionTest.php +++ b/module/Rest/test/Action/MercureInfoActionTest.php @@ -7,23 +7,19 @@ namespace ShlinkioTest\Shlink\Rest\Action; use Cake\Chronos\Chronos; use Laminas\Diactoros\Response\JsonResponse; use Laminas\Diactoros\ServerRequestFactory; +use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; -use Prophecy\Argument; -use Prophecy\PhpUnit\ProphecyTrait; -use Prophecy\Prophecy\ObjectProphecy; use Shlinkio\Shlink\Common\Mercure\JwtProviderInterface; use Shlinkio\Shlink\Rest\Action\MercureInfoAction; use Shlinkio\Shlink\Rest\Exception\MercureException; class MercureInfoActionTest extends TestCase { - use ProphecyTrait; - - private ObjectProphecy $provider; + private MockObject $provider; protected function setUp(): void { - $this->provider = $this->prophesize(JwtProviderInterface::class); + $this->provider = $this->createMock(JwtProviderInterface::class); } /** @@ -32,12 +28,11 @@ class MercureInfoActionTest extends TestCase */ public function throwsExceptionWhenConfigDoesNotHavePublicHost(array $mercureConfig): void { - $buildToken = $this->provider->buildSubscriptionToken(Argument::any())->willReturn('abc.123'); + $this->provider->expects($this->never())->method('buildSubscriptionToken'); - $action = new MercureInfoAction($this->provider->reveal(), $mercureConfig); + $action = new MercureInfoAction($this->provider, $mercureConfig); $this->expectException(MercureException::class); - $buildToken->shouldNotBeCalled(); $action->handle(ServerRequestFactory::fromGlobals()); } @@ -60,9 +55,9 @@ class MercureInfoActionTest extends TestCase */ public function returnsExpectedInfoWhenEverythingIsOk(?int $days): void { - $buildToken = $this->provider->buildSubscriptionToken(Argument::any())->willReturn('abc.123'); + $this->provider->expects($this->once())->method('buildSubscriptionToken')->willReturn('abc.123'); - $action = new MercureInfoAction($this->provider->reveal(), [ + $action = new MercureInfoAction($this->provider, [ 'public_hub_url' => 'http://foobar.com', 'jwt_days_duration' => $days, ]); @@ -79,7 +74,6 @@ class MercureInfoActionTest extends TestCase Chronos::now()->addDays($days ?? 1)->startOfDay(), Chronos::parse($payload['jwtExpiration'])->startOfDay(), ); - $buildToken->shouldHaveBeenCalledOnce(); } public function provideDays(): iterable diff --git a/module/Rest/test/Action/ShortUrl/CreateShortUrlActionTest.php b/module/Rest/test/Action/ShortUrl/CreateShortUrlActionTest.php index 40284969..140f0230 100644 --- a/module/Rest/test/Action/ShortUrl/CreateShortUrlActionTest.php +++ b/module/Rest/test/Action/ShortUrl/CreateShortUrlActionTest.php @@ -8,10 +8,8 @@ use Cake\Chronos\Chronos; use Laminas\Diactoros\Response\JsonResponse; use Laminas\Diactoros\ServerRequest; use Laminas\Diactoros\ServerRequestFactory; +use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; -use Prophecy\Argument; -use Prophecy\PhpUnit\ProphecyTrait; -use Prophecy\Prophecy\ObjectProphecy; use Shlinkio\Shlink\Common\Rest\DataTransformerInterface; use Shlinkio\Shlink\Core\Exception\ValidationException; use Shlinkio\Shlink\Core\Options\UrlShortenerOptions; @@ -23,23 +21,16 @@ use Shlinkio\Shlink\Rest\Entity\ApiKey; class CreateShortUrlActionTest extends TestCase { - use ProphecyTrait; - private CreateShortUrlAction $action; - private ObjectProphecy $urlShortener; - private ObjectProphecy $transformer; + private MockObject $urlShortener; + private MockObject $transformer; protected function setUp(): void { - $this->urlShortener = $this->prophesize(UrlShortener::class); - $this->transformer = $this->prophesize(DataTransformerInterface::class); - $this->transformer->transform(Argument::type(ShortUrl::class))->willReturn([]); + $this->urlShortener = $this->createMock(UrlShortener::class); + $this->transformer = $this->createMock(DataTransformerInterface::class); - $this->action = new CreateShortUrlAction( - $this->urlShortener->reveal(), - $this->transformer->reveal(), - new UrlShortenerOptions(), - ); + $this->action = new CreateShortUrlAction($this->urlShortener, $this->transformer, new UrlShortenerOptions()); } /** @test */ @@ -58,8 +49,12 @@ class CreateShortUrlActionTest extends TestCase ]; $expectedMeta['apiKey'] = $apiKey; - $shorten = $this->urlShortener->shorten(ShortUrlCreation::fromRawData($expectedMeta))->willReturn($shortUrl); - $transform = $this->transformer->transform($shortUrl)->willReturn(['shortUrl' => 'stringified_short_url']); + $this->urlShortener->expects($this->once())->method('shorten')->with( + ShortUrlCreation::fromRawData($expectedMeta), + )->willReturn($shortUrl); + $this->transformer->expects($this->once())->method('transform')->with($shortUrl)->willReturn( + ['shortUrl' => 'stringified_short_url'], + ); $request = ServerRequestFactory::fromGlobals()->withParsedBody($body)->withAttribute(ApiKey::class, $apiKey); @@ -69,8 +64,6 @@ class CreateShortUrlActionTest extends TestCase self::assertEquals(200, $response->getStatusCode()); self::assertEquals('stringified_short_url', $payload['shortUrl']); - $shorten->shouldHaveBeenCalledOnce(); - $transform->shouldHaveBeenCalledOnce(); } /** @@ -79,8 +72,8 @@ class CreateShortUrlActionTest extends TestCase */ public function anInvalidDomainReturnsError(string $domain): void { - $shortUrl = ShortUrl::createEmpty(); - $urlToShortCode = $this->urlShortener->shorten(Argument::cetera())->willReturn($shortUrl); + $this->urlShortener->expects($this->never())->method('shorten'); + $this->transformer->expects($this->never())->method('transform'); $request = (new ServerRequest())->withParsedBody([ 'longUrl' => 'http://www.domain.com/foo/bar', @@ -88,7 +81,6 @@ class CreateShortUrlActionTest extends TestCase ])->withAttribute(ApiKey::class, ApiKey::create()); $this->expectException(ValidationException::class); - $urlToShortCode->shouldNotBeCalled(); $this->action->handle($request); } diff --git a/module/Rest/test/Action/ShortUrl/DeleteShortUrlActionTest.php b/module/Rest/test/Action/ShortUrl/DeleteShortUrlActionTest.php index bc073cf6..30a8e647 100644 --- a/module/Rest/test/Action/ShortUrl/DeleteShortUrlActionTest.php +++ b/module/Rest/test/Action/ShortUrl/DeleteShortUrlActionTest.php @@ -5,39 +5,31 @@ declare(strict_types=1); namespace ShlinkioTest\Shlink\Rest\Action\ShortUrl; use Laminas\Diactoros\ServerRequestFactory; +use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; -use Prophecy\Argument; -use Prophecy\PhpUnit\ProphecyTrait; -use Prophecy\Prophecy\ObjectProphecy; use Shlinkio\Shlink\Core\ShortUrl\DeleteShortUrlServiceInterface; use Shlinkio\Shlink\Rest\Action\ShortUrl\DeleteShortUrlAction; use Shlinkio\Shlink\Rest\Entity\ApiKey; class DeleteShortUrlActionTest extends TestCase { - use ProphecyTrait; - private DeleteShortUrlAction $action; - private ObjectProphecy $service; + private MockObject $service; protected function setUp(): void { - $this->service = $this->prophesize(DeleteShortUrlServiceInterface::class); - $this->action = new DeleteShortUrlAction($this->service->reveal()); + $this->service = $this->createMock(DeleteShortUrlServiceInterface::class); + $this->action = new DeleteShortUrlAction($this->service); } /** @test */ public function emptyResponseIsReturnedIfProperlyDeleted(): void { $apiKey = ApiKey::create(); - $deleteByShortCode = $this->service->deleteByShortCode(Argument::any(), false, $apiKey)->will( - function (): void { - }, - ); + $this->service->expects($this->once())->method('deleteByShortCode'); $resp = $this->action->handle(ServerRequestFactory::fromGlobals()->withAttribute(ApiKey::class, $apiKey)); self::assertEquals(204, $resp->getStatusCode()); - $deleteByShortCode->shouldHaveBeenCalledOnce(); } } diff --git a/module/Rest/test/Action/ShortUrl/EditShortUrlActionTest.php b/module/Rest/test/Action/ShortUrl/EditShortUrlActionTest.php index 19cb27e9..94f3dbae 100644 --- a/module/Rest/test/Action/ShortUrl/EditShortUrlActionTest.php +++ b/module/Rest/test/Action/ShortUrl/EditShortUrlActionTest.php @@ -5,10 +5,8 @@ declare(strict_types=1); namespace ShlinkioTest\Shlink\Rest\Action\ShortUrl; use Laminas\Diactoros\ServerRequest; +use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; -use Prophecy\Argument; -use Prophecy\PhpUnit\ProphecyTrait; -use Prophecy\Prophecy\ObjectProphecy; use Shlinkio\Shlink\Core\Exception\ValidationException; use Shlinkio\Shlink\Core\ShortUrl\Entity\ShortUrl; use Shlinkio\Shlink\Core\ShortUrl\Helper\ShortUrlStringifier; @@ -19,15 +17,13 @@ use Shlinkio\Shlink\Rest\Entity\ApiKey; class EditShortUrlActionTest extends TestCase { - use ProphecyTrait; - private EditShortUrlAction $action; - private ObjectProphecy $shortUrlService; + private MockObject $shortUrlService; protected function setUp(): void { - $this->shortUrlService = $this->prophesize(ShortUrlServiceInterface::class); - $this->action = new EditShortUrlAction($this->shortUrlService->reveal(), new ShortUrlDataTransformer( + $this->shortUrlService = $this->createMock(ShortUrlServiceInterface::class); + $this->action = new EditShortUrlAction($this->shortUrlService, new ShortUrlDataTransformer( new ShortUrlStringifier([]), )); } @@ -38,6 +34,7 @@ class EditShortUrlActionTest extends TestCase $request = (new ServerRequest())->withParsedBody([ 'maxVisits' => 'invalid', ]); + $this->shortUrlService->expects($this->never())->method('updateShortUrl'); $this->expectException(ValidationException::class); @@ -52,13 +49,10 @@ class EditShortUrlActionTest extends TestCase ->withParsedBody([ 'maxVisits' => 5, ]); - $updateMeta = $this->shortUrlService->updateShortUrl(Argument::cetera())->willReturn( - ShortUrl::createEmpty(), - ); + $this->shortUrlService->expects($this->once())->method('updateShortUrl')->willReturn(ShortUrl::createEmpty()); $resp = $this->action->handle($request); self::assertEquals(200, $resp->getStatusCode()); - $updateMeta->shouldHaveBeenCalled(); } } diff --git a/module/Rest/test/Action/ShortUrl/ListShortUrlsActionTest.php b/module/Rest/test/Action/ShortUrl/ListShortUrlsActionTest.php index 65e6ebbf..068677d3 100644 --- a/module/Rest/test/Action/ShortUrl/ListShortUrlsActionTest.php +++ b/module/Rest/test/Action/ShortUrl/ListShortUrlsActionTest.php @@ -8,9 +8,8 @@ use Cake\Chronos\Chronos; use Laminas\Diactoros\Response\JsonResponse; use Laminas\Diactoros\ServerRequestFactory; use Pagerfanta\Adapter\ArrayAdapter; +use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; -use Prophecy\PhpUnit\ProphecyTrait; -use Prophecy\Prophecy\ObjectProphecy; use Shlinkio\Shlink\Common\Paginator\Paginator; use Shlinkio\Shlink\Core\ShortUrl\Helper\ShortUrlStringifier; use Shlinkio\Shlink\Core\ShortUrl\Model\ShortUrlsParams; @@ -21,16 +20,14 @@ use Shlinkio\Shlink\Rest\Entity\ApiKey; class ListShortUrlsActionTest extends TestCase { - use ProphecyTrait; - private ListShortUrlsAction $action; - private ObjectProphecy $service; + private MockObject $service; protected function setUp(): void { - $this->service = $this->prophesize(ShortUrlService::class); + $this->service = $this->createMock(ShortUrlService::class); - $this->action = new ListShortUrlsAction($this->service->reveal(), new ShortUrlDataTransformer( + $this->action = new ListShortUrlsAction($this->service, new ShortUrlDataTransformer( new ShortUrlStringifier([ 'hostname' => 'doma.in', 'schema' => 'https', @@ -54,7 +51,7 @@ class ListShortUrlsActionTest extends TestCase $apiKey = ApiKey::create(); $request = ServerRequestFactory::fromGlobals()->withQueryParams($query) ->withAttribute(ApiKey::class, $apiKey); - $listShortUrls = $this->service->listShortUrls(ShortUrlsParams::fromRawData([ + $this->service->expects($this->once())->method('listShortUrls')->with(ShortUrlsParams::fromRawData([ 'page' => $expectedPage, 'searchTerm' => $expectedSearchTerm, 'tags' => $expectedTags, @@ -71,7 +68,6 @@ class ListShortUrlsActionTest extends TestCase self::assertArrayHasKey('data', $payload['shortUrls']); self::assertEquals([], $payload['shortUrls']['data']); self::assertEquals(200, $response->getStatusCode()); - $listShortUrls->shouldHaveBeenCalledOnce(); } public function provideFilteringData(): iterable diff --git a/module/Rest/test/Action/ShortUrl/ResolveShortUrlActionTest.php b/module/Rest/test/Action/ShortUrl/ResolveShortUrlActionTest.php index 1b805c5f..0e91290f 100644 --- a/module/Rest/test/Action/ShortUrl/ResolveShortUrlActionTest.php +++ b/module/Rest/test/Action/ShortUrl/ResolveShortUrlActionTest.php @@ -5,9 +5,8 @@ declare(strict_types=1); namespace ShlinkioTest\Shlink\Rest\Action\ShortUrl; use Laminas\Diactoros\ServerRequest; +use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; -use Prophecy\PhpUnit\ProphecyTrait; -use Prophecy\Prophecy\ObjectProphecy; use Shlinkio\Shlink\Core\ShortUrl\Entity\ShortUrl; use Shlinkio\Shlink\Core\ShortUrl\Helper\ShortUrlStringifier; use Shlinkio\Shlink\Core\ShortUrl\Model\ShortUrlIdentifier; @@ -18,15 +17,13 @@ use Shlinkio\Shlink\Rest\Entity\ApiKey; class ResolveShortUrlActionTest extends TestCase { - use ProphecyTrait; - private ResolveShortUrlAction $action; - private ObjectProphecy $urlResolver; + private MockObject $urlResolver; protected function setUp(): void { - $this->urlResolver = $this->prophesize(ShortUrlResolverInterface::class); - $this->action = new ResolveShortUrlAction($this->urlResolver->reveal(), new ShortUrlDataTransformer( + $this->urlResolver = $this->createMock(ShortUrlResolverInterface::class); + $this->action = new ResolveShortUrlAction($this->urlResolver, new ShortUrlDataTransformer( new ShortUrlStringifier([]), )); } @@ -36,11 +33,10 @@ class ResolveShortUrlActionTest extends TestCase { $shortCode = 'abc123'; $apiKey = ApiKey::create(); - $this->urlResolver->resolveShortUrl( + $this->urlResolver->expects($this->once())->method('resolveShortUrl')->with( ShortUrlIdentifier::fromShortCodeAndDomain($shortCode), $apiKey, - )->willReturn(ShortUrl::withLongUrl('http://domain.com/foo/bar')) - ->shouldBeCalledOnce(); + )->willReturn(ShortUrl::withLongUrl('http://domain.com/foo/bar')); $request = (new ServerRequest())->withAttribute('shortCode', $shortCode)->withAttribute(ApiKey::class, $apiKey); $response = $this->action->handle($request); diff --git a/module/Rest/test/Action/ShortUrl/SingleStepCreateShortUrlActionTest.php b/module/Rest/test/Action/ShortUrl/SingleStepCreateShortUrlActionTest.php index 3fd29c2f..5e0867e7 100644 --- a/module/Rest/test/Action/ShortUrl/SingleStepCreateShortUrlActionTest.php +++ b/module/Rest/test/Action/ShortUrl/SingleStepCreateShortUrlActionTest.php @@ -5,10 +5,8 @@ declare(strict_types=1); namespace ShlinkioTest\Shlink\Rest\Action\ShortUrl; use Laminas\Diactoros\ServerRequest; +use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; -use Prophecy\Argument; -use Prophecy\PhpUnit\ProphecyTrait; -use Prophecy\Prophecy\ObjectProphecy; use Shlinkio\Shlink\Common\Rest\DataTransformerInterface; use Shlinkio\Shlink\Core\Options\UrlShortenerOptions; use Shlinkio\Shlink\Core\ShortUrl\Entity\ShortUrl; @@ -19,21 +17,18 @@ use Shlinkio\Shlink\Rest\Entity\ApiKey; class SingleStepCreateShortUrlActionTest extends TestCase { - use ProphecyTrait; - private SingleStepCreateShortUrlAction $action; - private ObjectProphecy $urlShortener; - private ObjectProphecy $transformer; + private MockObject $urlShortener; protected function setUp(): void { - $this->urlShortener = $this->prophesize(UrlShortenerInterface::class); - $this->transformer = $this->prophesize(DataTransformerInterface::class); - $this->transformer->transform(Argument::type(ShortUrl::class))->willReturn([]); + $this->urlShortener = $this->createMock(UrlShortenerInterface::class); + $transformer = $this->createMock(DataTransformerInterface::class); + $transformer->method('transform')->willReturn([]); $this->action = new SingleStepCreateShortUrlAction( - $this->urlShortener->reveal(), - $this->transformer->reveal(), + $this->urlShortener, + $transformer, new UrlShortenerOptions(), ); } @@ -46,13 +41,12 @@ class SingleStepCreateShortUrlActionTest extends TestCase $request = (new ServerRequest())->withQueryParams([ 'longUrl' => 'http://foobar.com', ])->withAttribute(ApiKey::class, $apiKey); - $generateShortCode = $this->urlShortener->shorten( + $this->urlShortener->expects($this->once())->method('shorten')->with( ShortUrlCreation::fromRawData(['apiKey' => $apiKey, 'longUrl' => 'http://foobar.com']), )->willReturn(ShortUrl::createEmpty()); $resp = $this->action->handle($request); self::assertEquals(200, $resp->getStatusCode()); - $generateShortCode->shouldHaveBeenCalled(); } } diff --git a/module/Rest/test/Action/Tag/DeleteTagsActionTest.php b/module/Rest/test/Action/Tag/DeleteTagsActionTest.php index 457507e8..cca532a4 100644 --- a/module/Rest/test/Action/Tag/DeleteTagsActionTest.php +++ b/module/Rest/test/Action/Tag/DeleteTagsActionTest.php @@ -5,25 +5,21 @@ declare(strict_types=1); namespace ShlinkioTest\Shlink\Rest\Action\Tag; use Laminas\Diactoros\ServerRequest; +use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; -use Prophecy\Argument; -use Prophecy\PhpUnit\ProphecyTrait; -use Prophecy\Prophecy\ObjectProphecy; use Shlinkio\Shlink\Core\Tag\TagServiceInterface; use Shlinkio\Shlink\Rest\Action\Tag\DeleteTagsAction; use Shlinkio\Shlink\Rest\Entity\ApiKey; class DeleteTagsActionTest extends TestCase { - use ProphecyTrait; - private DeleteTagsAction $action; - private ObjectProphecy $tagService; + private MockObject $tagService; protected function setUp(): void { - $this->tagService = $this->prophesize(TagServiceInterface::class); - $this->action = new DeleteTagsAction($this->tagService->reveal()); + $this->tagService = $this->createMock(TagServiceInterface::class); + $this->action = new DeleteTagsAction($this->tagService); } /** @@ -35,12 +31,14 @@ class DeleteTagsActionTest extends TestCase $request = (new ServerRequest()) ->withQueryParams(['tags' => $tags]) ->withAttribute(ApiKey::class, ApiKey::create()); - $deleteTags = $this->tagService->deleteTags($tags ?: [], Argument::type(ApiKey::class)); + $this->tagService->expects($this->once())->method('deleteTags')->with( + $tags ?? [], + $this->isInstanceOf(ApiKey::class), + ); $response = $this->action->handle($request); self::assertEquals(204, $response->getStatusCode()); - $deleteTags->shouldHaveBeenCalled(); } public function provideTags(): iterable diff --git a/module/Rest/test/Action/Tag/ListTagsActionTest.php b/module/Rest/test/Action/Tag/ListTagsActionTest.php index e362aca9..d340c82f 100644 --- a/module/Rest/test/Action/Tag/ListTagsActionTest.php +++ b/module/Rest/test/Action/Tag/ListTagsActionTest.php @@ -7,10 +7,8 @@ namespace ShlinkioTest\Shlink\Rest\Action\Tag; use Laminas\Diactoros\Response\JsonResponse; use Laminas\Diactoros\ServerRequestFactory; use Pagerfanta\Adapter\ArrayAdapter; +use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; -use Prophecy\Argument; -use Prophecy\PhpUnit\ProphecyTrait; -use Prophecy\Prophecy\ObjectProphecy; use Psr\Http\Message\ServerRequestInterface; use Shlinkio\Shlink\Common\Paginator\Paginator; use Shlinkio\Shlink\Core\Tag\Entity\Tag; @@ -23,15 +21,13 @@ use function count; class ListTagsActionTest extends TestCase { - use ProphecyTrait; - private ListTagsAction $action; - private ObjectProphecy $tagService; + private MockObject $tagService; protected function setUp(): void { - $this->tagService = $this->prophesize(TagServiceInterface::class); - $this->action = new ListTagsAction($this->tagService->reveal()); + $this->tagService = $this->createMock(TagServiceInterface::class); + $this->action = new ListTagsAction($this->tagService); } /** @@ -42,9 +38,10 @@ class ListTagsActionTest extends TestCase { $tags = [new Tag('foo'), new Tag('bar')]; $tagsCount = count($tags); - $listTags = $this->tagService->listTags(Argument::any(), Argument::type(ApiKey::class))->willReturn( - new Paginator(new ArrayAdapter($tags)), - ); + $this->tagService->expects($this->once())->method('listTags')->with( + $this->anything(), + $this->isInstanceOf(ApiKey::class), + )->willReturn(new Paginator(new ArrayAdapter($tags))); /** @var JsonResponse $resp */ $resp = $this->action->handle($this->requestWithApiKey()->withQueryParams($query)); @@ -62,7 +59,6 @@ class ListTagsActionTest extends TestCase ], ], ], $payload); - $listTags->shouldHaveBeenCalled(); } public function provideNoStatsQueries(): iterable @@ -80,9 +76,10 @@ class ListTagsActionTest extends TestCase new TagInfo('bar', 3, 10), ]; $itemsCount = count($stats); - $tagsInfo = $this->tagService->tagsInfo(Argument::any(), Argument::type(ApiKey::class))->willReturn( - new Paginator(new ArrayAdapter($stats)), - ); + $this->tagService->expects($this->once())->method('tagsInfo')->with( + $this->anything(), + $this->isInstanceOf(ApiKey::class), + )->willReturn(new Paginator(new ArrayAdapter($stats))); $req = $this->requestWithApiKey()->withQueryParams(['withStats' => 'true']); /** @var JsonResponse $resp */ @@ -102,7 +99,6 @@ class ListTagsActionTest extends TestCase ], ], ], $payload); - $tagsInfo->shouldHaveBeenCalled(); } private function requestWithApiKey(): ServerRequestInterface diff --git a/module/Rest/test/Action/Tag/TagsStatsActionTest.php b/module/Rest/test/Action/Tag/TagsStatsActionTest.php index 44e6afb0..8e0e8e74 100644 --- a/module/Rest/test/Action/Tag/TagsStatsActionTest.php +++ b/module/Rest/test/Action/Tag/TagsStatsActionTest.php @@ -7,10 +7,8 @@ namespace ShlinkioTest\Shlink\Rest\Action\Tag; use Laminas\Diactoros\Response\JsonResponse; use Laminas\Diactoros\ServerRequestFactory; use Pagerfanta\Adapter\ArrayAdapter; +use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; -use Prophecy\Argument; -use Prophecy\PhpUnit\ProphecyTrait; -use Prophecy\Prophecy\ObjectProphecy; use Psr\Http\Message\ServerRequestInterface; use Shlinkio\Shlink\Common\Paginator\Paginator; use Shlinkio\Shlink\Core\Tag\Model\TagInfo; @@ -22,15 +20,13 @@ use function count; class TagsStatsActionTest extends TestCase { - use ProphecyTrait; - private TagsStatsAction $action; - private ObjectProphecy $tagService; + private MockObject $tagService; protected function setUp(): void { - $this->tagService = $this->prophesize(TagServiceInterface::class); - $this->action = new TagsStatsAction($this->tagService->reveal()); + $this->tagService = $this->createMock(TagServiceInterface::class); + $this->action = new TagsStatsAction($this->tagService); } /** @test */ @@ -41,9 +37,10 @@ class TagsStatsActionTest extends TestCase new TagInfo('bar', 3, 10), ]; $itemsCount = count($stats); - $tagsInfo = $this->tagService->tagsInfo(Argument::any(), Argument::type(ApiKey::class))->willReturn( - new Paginator(new ArrayAdapter($stats)), - ); + $this->tagService->expects($this->once())->method('tagsInfo')->with( + $this->anything(), + $this->isInstanceOf(ApiKey::class), + )->willReturn(new Paginator(new ArrayAdapter($stats))); $req = $this->requestWithApiKey()->withQueryParams(['withStats' => 'true']); /** @var JsonResponse $resp */ @@ -62,7 +59,6 @@ class TagsStatsActionTest extends TestCase ], ], ], $payload); - $tagsInfo->shouldHaveBeenCalled(); } private function requestWithApiKey(): ServerRequestInterface diff --git a/module/Rest/test/Action/Tag/UpdateTagActionTest.php b/module/Rest/test/Action/Tag/UpdateTagActionTest.php index aea611ac..d1424849 100644 --- a/module/Rest/test/Action/Tag/UpdateTagActionTest.php +++ b/module/Rest/test/Action/Tag/UpdateTagActionTest.php @@ -5,10 +5,8 @@ declare(strict_types=1); namespace ShlinkioTest\Shlink\Rest\Action\Tag; use Laminas\Diactoros\ServerRequestFactory; +use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; -use Prophecy\Argument; -use Prophecy\PhpUnit\ProphecyTrait; -use Prophecy\Prophecy\ObjectProphecy; use Psr\Http\Message\ServerRequestInterface; use Shlinkio\Shlink\Core\Exception\ValidationException; use Shlinkio\Shlink\Core\Tag\Entity\Tag; @@ -19,15 +17,13 @@ use Shlinkio\Shlink\Rest\Entity\ApiKey; class UpdateTagActionTest extends TestCase { - use ProphecyTrait; - private UpdateTagAction $action; - private ObjectProphecy $tagService; + private MockObject $tagService; protected function setUp(): void { - $this->tagService = $this->prophesize(TagServiceInterface::class); - $this->action = new UpdateTagAction($this->tagService->reveal()); + $this->tagService = $this->createMock(TagServiceInterface::class); + $this->action = new UpdateTagAction($this->tagService); } /** @@ -57,15 +53,14 @@ class UpdateTagActionTest extends TestCase 'oldName' => 'foo', 'newName' => 'bar', ]); - $rename = $this->tagService->renameTag( + $this->tagService->expects($this->once())->method('renameTag')->with( TagRenaming::fromNames('foo', 'bar'), - Argument::type(ApiKey::class), + $this->isInstanceOf(ApiKey::class), )->willReturn(new Tag('bar')); $resp = $this->action->handle($request); self::assertEquals(204, $resp->getStatusCode()); - $rename->shouldHaveBeenCalled(); } private function requestWithApiKey(): ServerRequestInterface diff --git a/module/Rest/test/Action/Visit/DomainVisitsActionTest.php b/module/Rest/test/Action/Visit/DomainVisitsActionTest.php index 6e3f2fe8..b56f557b 100644 --- a/module/Rest/test/Action/Visit/DomainVisitsActionTest.php +++ b/module/Rest/test/Action/Visit/DomainVisitsActionTest.php @@ -6,10 +6,8 @@ namespace ShlinkioTest\Shlink\Rest\Action\Visit; use Laminas\Diactoros\ServerRequestFactory; use Pagerfanta\Adapter\ArrayAdapter; +use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; -use Prophecy\Argument; -use Prophecy\PhpUnit\ProphecyTrait; -use Prophecy\Prophecy\ObjectProphecy; use Shlinkio\Shlink\Common\Paginator\Paginator; use Shlinkio\Shlink\Core\Visit\Model\VisitsParams; use Shlinkio\Shlink\Core\Visit\VisitsStatsHelperInterface; @@ -18,15 +16,13 @@ use Shlinkio\Shlink\Rest\Entity\ApiKey; class DomainVisitsActionTest extends TestCase { - use ProphecyTrait; - private DomainVisitsAction $action; - private ObjectProphecy $visitsHelper; + private MockObject $visitsHelper; protected function setUp(): void { - $this->visitsHelper = $this->prophesize(VisitsStatsHelperInterface::class); - $this->action = new DomainVisitsAction($this->visitsHelper->reveal(), 'the_default.com'); + $this->visitsHelper = $this->createMock(VisitsStatsHelperInterface::class); + $this->action = new DomainVisitsAction($this->visitsHelper, 'the_default.com'); } /** @@ -36,9 +32,9 @@ class DomainVisitsActionTest extends TestCase public function providingCorrectDomainReturnsVisits(string $providedDomain, string $expectedDomain): void { $apiKey = ApiKey::create(); - $getVisits = $this->visitsHelper->visitsForDomain( + $this->visitsHelper->expects($this->once())->method('visitsForDomain')->with( $expectedDomain, - Argument::type(VisitsParams::class), + $this->isInstanceOf(VisitsParams::class), $apiKey, )->willReturn(new Paginator(new ArrayAdapter([]))); @@ -48,7 +44,6 @@ class DomainVisitsActionTest extends TestCase ); self::assertEquals(200, $response->getStatusCode()); - $getVisits->shouldHaveBeenCalledOnce(); } public function provideDomainAuthorities(): iterable diff --git a/module/Rest/test/Action/Visit/GlobalVisitsActionTest.php b/module/Rest/test/Action/Visit/GlobalVisitsActionTest.php index d5f94250..87830cb5 100644 --- a/module/Rest/test/Action/Visit/GlobalVisitsActionTest.php +++ b/module/Rest/test/Action/Visit/GlobalVisitsActionTest.php @@ -6,9 +6,8 @@ namespace ShlinkioTest\Shlink\Rest\Action\Visit; use Laminas\Diactoros\Response\JsonResponse; use Laminas\Diactoros\ServerRequestFactory; +use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; -use Prophecy\PhpUnit\ProphecyTrait; -use Prophecy\Prophecy\ObjectProphecy; use Shlinkio\Shlink\Core\Visit\Model\VisitsStats; use Shlinkio\Shlink\Core\Visit\VisitsStatsHelperInterface; use Shlinkio\Shlink\Rest\Action\Visit\GlobalVisitsAction; @@ -16,15 +15,13 @@ use Shlinkio\Shlink\Rest\Entity\ApiKey; class GlobalVisitsActionTest extends TestCase { - use ProphecyTrait; - private GlobalVisitsAction $action; - private ObjectProphecy $helper; + private MockObject $helper; protected function setUp(): void { - $this->helper = $this->prophesize(VisitsStatsHelperInterface::class); - $this->action = new GlobalVisitsAction($this->helper->reveal()); + $this->helper = $this->createMock(VisitsStatsHelperInterface::class); + $this->action = new GlobalVisitsAction($this->helper); } /** @test */ @@ -32,13 +29,12 @@ class GlobalVisitsActionTest extends TestCase { $apiKey = ApiKey::create(); $stats = new VisitsStats(5, 3); - $getStats = $this->helper->getVisitsStats($apiKey)->willReturn($stats); + $this->helper->expects($this->once())->method('getVisitsStats')->with($apiKey)->willReturn($stats); /** @var JsonResponse $resp */ $resp = $this->action->handle(ServerRequestFactory::fromGlobals()->withAttribute(ApiKey::class, $apiKey)); $payload = $resp->getPayload(); self::assertEquals($payload, ['visits' => $stats]); - $getStats->shouldHaveBeenCalledOnce(); } } diff --git a/module/Rest/test/Action/Visit/NonOrphanVisitsActionTest.php b/module/Rest/test/Action/Visit/NonOrphanVisitsActionTest.php index 4ecf5b88..4cf6d8a2 100644 --- a/module/Rest/test/Action/Visit/NonOrphanVisitsActionTest.php +++ b/module/Rest/test/Action/Visit/NonOrphanVisitsActionTest.php @@ -7,10 +7,8 @@ namespace ShlinkioTest\Shlink\Rest\Action\Visit; use Laminas\Diactoros\Response\JsonResponse; use Laminas\Diactoros\ServerRequestFactory; use Pagerfanta\Adapter\ArrayAdapter; +use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; -use Prophecy\Argument; -use Prophecy\PhpUnit\ProphecyTrait; -use Prophecy\Prophecy\ObjectProphecy; use Shlinkio\Shlink\Common\Paginator\Paginator; use Shlinkio\Shlink\Core\Visit\Model\VisitsParams; use Shlinkio\Shlink\Core\Visit\VisitsStatsHelperInterface; @@ -19,24 +17,23 @@ use Shlinkio\Shlink\Rest\Entity\ApiKey; class NonOrphanVisitsActionTest extends TestCase { - use ProphecyTrait; - private NonOrphanVisitsAction $action; - private ObjectProphecy $visitsHelper; + private MockObject $visitsHelper; protected function setUp(): void { - $this->visitsHelper = $this->prophesize(VisitsStatsHelperInterface::class); - $this->action = new NonOrphanVisitsAction($this->visitsHelper->reveal()); + $this->visitsHelper = $this->createMock(VisitsStatsHelperInterface::class); + $this->action = new NonOrphanVisitsAction($this->visitsHelper); } /** @test */ public function requestIsHandled(): void { $apiKey = ApiKey::create(); - $getVisits = $this->visitsHelper->nonOrphanVisits(Argument::type(VisitsParams::class), $apiKey)->willReturn( - new Paginator(new ArrayAdapter([])), - ); + $this->visitsHelper->expects($this->once())->method('nonOrphanVisits')->with( + $this->isInstanceOf(VisitsParams::class), + $apiKey, + )->willReturn(new Paginator(new ArrayAdapter([]))); /** @var JsonResponse $response */ $response = $this->action->handle(ServerRequestFactory::fromGlobals()->withAttribute(ApiKey::class, $apiKey)); @@ -44,6 +41,5 @@ class NonOrphanVisitsActionTest extends TestCase self::assertEquals(200, $response->getStatusCode()); self::assertArrayHasKey('visits', $payload); - $getVisits->shouldHaveBeenCalledOnce(); } } diff --git a/module/Rest/test/Action/Visit/OrphanVisitsActionTest.php b/module/Rest/test/Action/Visit/OrphanVisitsActionTest.php index ca1ae4e5..7ad77425 100644 --- a/module/Rest/test/Action/Visit/OrphanVisitsActionTest.php +++ b/module/Rest/test/Action/Visit/OrphanVisitsActionTest.php @@ -7,10 +7,8 @@ namespace ShlinkioTest\Shlink\Rest\Action\Visit; use Laminas\Diactoros\Response\JsonResponse; use Laminas\Diactoros\ServerRequestFactory; use Pagerfanta\Adapter\ArrayAdapter; +use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; -use Prophecy\Argument; -use Prophecy\PhpUnit\ProphecyTrait; -use Prophecy\Prophecy\ObjectProphecy; use Shlinkio\Shlink\Common\Paginator\Paginator; use Shlinkio\Shlink\Common\Rest\DataTransformerInterface; use Shlinkio\Shlink\Core\Visit\Entity\Visit; @@ -23,18 +21,16 @@ use function count; class OrphanVisitsActionTest extends TestCase { - use ProphecyTrait; - private OrphanVisitsAction $action; - private ObjectProphecy $visitsHelper; - private ObjectProphecy $orphanVisitTransformer; + private MockObject $visitsHelper; + private MockObject $orphanVisitTransformer; protected function setUp(): void { - $this->visitsHelper = $this->prophesize(VisitsStatsHelperInterface::class); - $this->orphanVisitTransformer = $this->prophesize(DataTransformerInterface::class); + $this->visitsHelper = $this->createMock(VisitsStatsHelperInterface::class); + $this->orphanVisitTransformer = $this->createMock(DataTransformerInterface::class); - $this->action = new OrphanVisitsAction($this->visitsHelper->reveal(), $this->orphanVisitTransformer->reveal()); + $this->action = new OrphanVisitsAction($this->visitsHelper, $this->orphanVisitTransformer); } /** @test */ @@ -42,11 +38,13 @@ class OrphanVisitsActionTest extends TestCase { $visitor = Visitor::emptyInstance(); $visits = [Visit::forInvalidShortUrl($visitor), Visit::forRegularNotFound($visitor)]; - $orphanVisits = $this->visitsHelper->orphanVisits(Argument::type(VisitsParams::class))->willReturn( - new Paginator(new ArrayAdapter($visits)), - ); + $this->visitsHelper->expects($this->once())->method('orphanVisits')->with( + $this->isInstanceOf(VisitsParams::class), + )->willReturn(new Paginator(new ArrayAdapter($visits))); $visitsAmount = count($visits); - $transform = $this->orphanVisitTransformer->transform(Argument::type(Visit::class))->willReturn([]); + $this->orphanVisitTransformer->expects($this->exactly($visitsAmount))->method('transform')->with( + $this->isInstanceOf(Visit::class), + )->willReturn([]); /** @var JsonResponse $response */ $response = $this->action->handle(ServerRequestFactory::fromGlobals()); @@ -54,7 +52,5 @@ class OrphanVisitsActionTest extends TestCase self::assertCount($visitsAmount, $payload['visits']['data']); self::assertEquals(200, $response->getStatusCode()); - $orphanVisits->shouldHaveBeenCalledOnce(); - $transform->shouldHaveBeenCalledTimes($visitsAmount); } } diff --git a/module/Rest/test/Action/Visit/ShortUrlVisitsActionTest.php b/module/Rest/test/Action/Visit/ShortUrlVisitsActionTest.php index be1a88e8..8302dd27 100644 --- a/module/Rest/test/Action/Visit/ShortUrlVisitsActionTest.php +++ b/module/Rest/test/Action/Visit/ShortUrlVisitsActionTest.php @@ -7,10 +7,8 @@ namespace ShlinkioTest\Shlink\Rest\Action\Visit; use Cake\Chronos\Chronos; use Laminas\Diactoros\ServerRequestFactory; use Pagerfanta\Adapter\ArrayAdapter; +use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; -use Prophecy\Argument; -use Prophecy\PhpUnit\ProphecyTrait; -use Prophecy\Prophecy\ObjectProphecy; use Psr\Http\Message\ServerRequestInterface; use Shlinkio\Shlink\Common\Paginator\Paginator; use Shlinkio\Shlink\Common\Util\DateRange; @@ -22,27 +20,24 @@ use Shlinkio\Shlink\Rest\Entity\ApiKey; class ShortUrlVisitsActionTest extends TestCase { - use ProphecyTrait; - private ShortUrlVisitsAction $action; - private ObjectProphecy $visitsHelper; + private MockObject $visitsHelper; protected function setUp(): void { - $this->visitsHelper = $this->prophesize(VisitsStatsHelperInterface::class); - $this->action = new ShortUrlVisitsAction($this->visitsHelper->reveal()); + $this->visitsHelper = $this->createMock(VisitsStatsHelperInterface::class); + $this->action = new ShortUrlVisitsAction($this->visitsHelper); } /** @test */ public function providingCorrectShortCodeReturnsVisits(): void { $shortCode = 'abc123'; - $this->visitsHelper->visitsForShortUrl( + $this->visitsHelper->expects($this->once())->method('visitsForShortUrl')->with( ShortUrlIdentifier::fromShortCodeAndDomain($shortCode), - Argument::type(VisitsParams::class), - Argument::type(ApiKey::class), - )->willReturn(new Paginator(new ArrayAdapter([]))) - ->shouldBeCalledOnce(); + $this->isInstanceOf(VisitsParams::class), + $this->isInstanceOf(ApiKey::class), + )->willReturn(new Paginator(new ArrayAdapter([]))); $response = $this->action->handle($this->requestWithApiKey()->withAttribute('shortCode', $shortCode)); self::assertEquals(200, $response->getStatusCode()); @@ -52,13 +47,15 @@ class ShortUrlVisitsActionTest extends TestCase public function paramsAreReadFromQuery(): void { $shortCode = 'abc123'; - $this->visitsHelper->visitsForShortUrl(ShortUrlIdentifier::fromShortCodeAndDomain($shortCode), new VisitsParams( - DateRange::until(Chronos::parse('2016-01-01 00:00:00')), - 3, - 10, - ), Argument::type(ApiKey::class)) - ->willReturn(new Paginator(new ArrayAdapter([]))) - ->shouldBeCalledOnce(); + $this->visitsHelper->expects($this->once())->method('visitsForShortUrl')->with( + ShortUrlIdentifier::fromShortCodeAndDomain($shortCode), + new VisitsParams( + DateRange::until(Chronos::parse('2016-01-01 00:00:00')), + 3, + 10, + ), + $this->isInstanceOf(ApiKey::class), + )->willReturn(new Paginator(new ArrayAdapter([]))); $response = $this->action->handle( $this->requestWithApiKey()->withAttribute('shortCode', $shortCode) diff --git a/module/Rest/test/Action/Visit/TagVisitsActionTest.php b/module/Rest/test/Action/Visit/TagVisitsActionTest.php index f413a9eb..fd924d17 100644 --- a/module/Rest/test/Action/Visit/TagVisitsActionTest.php +++ b/module/Rest/test/Action/Visit/TagVisitsActionTest.php @@ -6,10 +6,8 @@ namespace ShlinkioTest\Shlink\Rest\Action\Visit; use Laminas\Diactoros\ServerRequestFactory; use Pagerfanta\Adapter\ArrayAdapter; +use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; -use Prophecy\Argument; -use Prophecy\PhpUnit\ProphecyTrait; -use Prophecy\Prophecy\ObjectProphecy; use Shlinkio\Shlink\Common\Paginator\Paginator; use Shlinkio\Shlink\Core\Visit\Model\VisitsParams; use Shlinkio\Shlink\Core\Visit\VisitsStatsHelperInterface; @@ -18,15 +16,13 @@ use Shlinkio\Shlink\Rest\Entity\ApiKey; class TagVisitsActionTest extends TestCase { - use ProphecyTrait; - private TagVisitsAction $action; - private ObjectProphecy $visitsHelper; + private MockObject $visitsHelper; protected function setUp(): void { - $this->visitsHelper = $this->prophesize(VisitsStatsHelperInterface::class); - $this->action = new TagVisitsAction($this->visitsHelper->reveal()); + $this->visitsHelper = $this->createMock(VisitsStatsHelperInterface::class); + $this->action = new TagVisitsAction($this->visitsHelper); } /** @test */ @@ -34,15 +30,16 @@ class TagVisitsActionTest extends TestCase { $tag = 'foo'; $apiKey = ApiKey::create(); - $getVisits = $this->visitsHelper->visitsForTag($tag, Argument::type(VisitsParams::class), $apiKey)->willReturn( - new Paginator(new ArrayAdapter([])), - ); + $this->visitsHelper->expects($this->once())->method('visitsForTag')->with( + $tag, + $this->isInstanceOf(VisitsParams::class), + $apiKey, + )->willReturn(new Paginator(new ArrayAdapter([]))); $response = $this->action->handle( ServerRequestFactory::fromGlobals()->withAttribute('tag', $tag)->withAttribute(ApiKey::class, $apiKey), ); self::assertEquals(200, $response->getStatusCode()); - $getVisits->shouldHaveBeenCalledOnce(); } } diff --git a/module/Rest/test/ApiKey/InitialApiKeyDelegatorTest.php b/module/Rest/test/ApiKey/InitialApiKeyDelegatorTest.php index 1db53b80..a44700a6 100644 --- a/module/Rest/test/ApiKey/InitialApiKeyDelegatorTest.php +++ b/module/Rest/test/ApiKey/InitialApiKeyDelegatorTest.php @@ -7,10 +7,8 @@ namespace ShlinkioTest\Shlink\Rest\ApiKey; use Doctrine\ORM\EntityManager; use Doctrine\ORM\EntityManagerInterface; use Mezzio\Application; +use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; -use Prophecy\Argument; -use Prophecy\PhpUnit\ProphecyTrait; -use Prophecy\Prophecy\ObjectProphecy; use Psr\Container\ContainerInterface; use Shlinkio\Shlink\Rest\ApiKey\InitialApiKeyDelegator; use Shlinkio\Shlink\Rest\ApiKey\Repository\ApiKeyRepositoryInterface; @@ -18,15 +16,13 @@ use Shlinkio\Shlink\Rest\Entity\ApiKey; class InitialApiKeyDelegatorTest extends TestCase { - use ProphecyTrait; - private InitialApiKeyDelegator $delegator; - private ObjectProphecy $container; + private MockObject $container; protected function setUp(): void { $this->delegator = new InitialApiKeyDelegator(); - $this->container = $this->prophesize(ContainerInterface::class); + $this->container = $this->createMock(ContainerInterface::class); } /** @@ -35,21 +31,21 @@ class InitialApiKeyDelegatorTest extends TestCase */ public function apiKeyIsInitializedWhenAppropriate(array $config, int $expectedCalls): void { - $app = $this->prophesize(Application::class)->reveal(); - $apiKeyRepo = $this->prophesize(ApiKeyRepositoryInterface::class); - $em = $this->prophesize(EntityManagerInterface::class); + $app = $this->createMock(Application::class); + $apiKeyRepo = $this->createMock(ApiKeyRepositoryInterface::class); + $apiKeyRepo->expects($this->exactly($expectedCalls))->method('createInitialApiKey'); + $em = $this->createMock(EntityManagerInterface::class); + $em->expects($this->exactly($expectedCalls))->method('getRepository')->with(ApiKey::class)->willReturn( + $apiKeyRepo, + ); + $this->container->expects($this->exactly($expectedCalls + 1))->method('get')->willReturnMap([ + ['config', $config], + [EntityManager::class, $em], + ]); - $getConfig = $this->container->get('config')->willReturn($config); - $getRepo = $em->getRepository(ApiKey::class)->willReturn($apiKeyRepo->reveal()); - $getEm = $this->container->get(EntityManager::class)->willReturn($em->reveal()); - - $result = ($this->delegator)($this->container->reveal(), '', fn () => $app); + $result = ($this->delegator)($this->container, '', fn () => $app); self::assertSame($result, $app); - $getConfig->shouldHaveBeenCalledOnce(); - $getRepo->shouldHaveBeenCalledTimes($expectedCalls); - $getEm->shouldHaveBeenCalledTimes($expectedCalls); - $apiKeyRepo->createInitialApiKey(Argument::any())->shouldHaveBeenCalledTimes($expectedCalls); } public function provideConfigs(): iterable diff --git a/module/Rest/test/Middleware/AuthenticationMiddlewareTest.php b/module/Rest/test/Middleware/AuthenticationMiddlewareTest.php index eef78ab7..03379921 100644 --- a/module/Rest/test/Middleware/AuthenticationMiddlewareTest.php +++ b/module/Rest/test/Middleware/AuthenticationMiddlewareTest.php @@ -10,10 +10,8 @@ use Laminas\Diactoros\ServerRequest; use Laminas\Diactoros\ServerRequestFactory; use Mezzio\Router\Route; use Mezzio\Router\RouteResult; +use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; -use Prophecy\Argument; -use Prophecy\PhpUnit\ProphecyTrait; -use Prophecy\Prophecy\ObjectProphecy; use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Server\MiddlewareInterface; use Psr\Http\Server\RequestHandlerInterface; @@ -29,21 +27,19 @@ use function Laminas\Stratigility\middleware; class AuthenticationMiddlewareTest extends TestCase { - use ProphecyTrait; - private AuthenticationMiddleware $middleware; - private ObjectProphecy $apiKeyService; - private ObjectProphecy $handler; + private MockObject $apiKeyService; + private MockObject $handler; protected function setUp(): void { - $this->apiKeyService = $this->prophesize(ApiKeyServiceInterface::class); + $this->apiKeyService = $this->createMock(ApiKeyServiceInterface::class); $this->middleware = new AuthenticationMiddleware( - $this->apiKeyService->reveal(), + $this->apiKeyService, [HealthAction::class], ['with_query_api_key'], ); - $this->handler = $this->prophesize(RequestHandlerInterface::class); + $this->handler = $this->createMock(RequestHandlerInterface::class); } /** @@ -52,13 +48,10 @@ class AuthenticationMiddlewareTest extends TestCase */ public function someSituationsFallbackToNextMiddleware(ServerRequestInterface $request): void { - $handle = $this->handler->handle($request)->willReturn(new Response()); - $checkApiKey = $this->apiKeyService->check(Argument::any()); + $this->handler->expects($this->once())->method('handle')->with($request)->willReturn(new Response()); + $this->apiKeyService->expects($this->never())->method('check'); - $this->middleware->process($request, $this->handler->reveal()); - - $handle->shouldHaveBeenCalledOnce(); - $checkApiKey->shouldNotHaveBeenCalled(); + $this->middleware->process($request, $this->handler); } public function provideRequestsWithoutAuth(): iterable @@ -90,12 +83,12 @@ class AuthenticationMiddlewareTest extends TestCase ServerRequestInterface $request, string $expectedMessage, ): void { - $this->apiKeyService->check(Argument::any())->shouldNotBeCalled(); - $this->handler->handle($request)->shouldNotBeCalled(); + $this->apiKeyService->expects($this->never())->method('check'); + $this->handler->expects($this->never())->method('handle'); $this->expectException(MissingAuthenticationException::class); $this->expectExceptionMessage($expectedMessage); - $this->middleware->process($request, $this->handler->reveal()); + $this->middleware->process($request, $this->handler); } public function provideRequestsWithoutApiKey(): iterable @@ -127,12 +120,14 @@ class AuthenticationMiddlewareTest extends TestCase ) ->withHeader('X-Api-Key', $apiKey); - $this->apiKeyService->check($apiKey)->willReturn(new ApiKeyCheckResult())->shouldBeCalledOnce(); - $this->handler->handle($request)->shouldNotBeCalled(); + $this->apiKeyService->expects($this->once())->method('check')->with($apiKey)->willReturn( + new ApiKeyCheckResult(), + ); + $this->handler->expects($this->never())->method('handle'); $this->expectException(VerifyAuthenticationException::class); $this->expectExceptionMessage('Provided API key does not exist or is invalid'); - $this->middleware->process($request, $this->handler->reveal()); + $this->middleware->process($request, $this->handler); } /** @test */ @@ -147,13 +142,14 @@ class AuthenticationMiddlewareTest extends TestCase ) ->withHeader('X-Api-Key', $key); - $handle = $this->handler->handle($request->withAttribute(ApiKey::class, $apiKey))->willReturn(new Response()); - $checkApiKey = $this->apiKeyService->check($key)->willReturn(new ApiKeyCheckResult($apiKey)); + $this->handler->expects($this->once())->method('handle')->with( + $request->withAttribute(ApiKey::class, $apiKey), + )->willReturn(new Response()); + $this->apiKeyService->expects($this->once())->method('check')->with($key)->willReturn( + new ApiKeyCheckResult($apiKey), + ); - $this->middleware->process($request, $this->handler->reveal()); - - $handle->shouldHaveBeenCalledOnce(); - $checkApiKey->shouldHaveBeenCalledOnce(); + $this->middleware->process($request, $this->handler); } private function getDummyMiddleware(): MiddlewareInterface diff --git a/module/Rest/test/Middleware/BodyParserMiddlewareTest.php b/module/Rest/test/Middleware/BodyParserMiddlewareTest.php index f254197e..63354a76 100644 --- a/module/Rest/test/Middleware/BodyParserMiddlewareTest.php +++ b/module/Rest/test/Middleware/BodyParserMiddlewareTest.php @@ -7,20 +7,14 @@ namespace ShlinkioTest\Shlink\Rest\Middleware; use Laminas\Diactoros\Response; use Laminas\Diactoros\ServerRequest; use Laminas\Diactoros\Stream; +use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; -use Prophecy\Argument; -use Prophecy\PhpUnit\ProphecyTrait; -use Prophecy\Prophecy\ProphecyInterface; use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Server\RequestHandlerInterface; use Shlinkio\Shlink\Rest\Middleware\BodyParserMiddleware; -use function array_shift; - class BodyParserMiddlewareTest extends TestCase { - use ProphecyTrait; - private BodyParserMiddleware $middleware; protected function setUp(): void @@ -34,11 +28,11 @@ class BodyParserMiddlewareTest extends TestCase */ public function requestsFromOtherMethodsJustFallbackToNextMiddleware(string $method): void { - $request = $this->prophesize(ServerRequestInterface::class); - $request->getMethod()->willReturn($method); - $request->getParsedBody()->willReturn([]); + $request = $this->createMock(ServerRequestInterface::class); + $request->method('getMethod')->willReturn($method); + $request->method('getParsedBody')->willReturn([]); - self::assertHandlingRequestJustFallsBackToNext($request); + $this->assertHandlingRequestJustFallsBackToNext($request); } public function provideIgnoredRequestMethods(): iterable @@ -51,25 +45,21 @@ class BodyParserMiddlewareTest extends TestCase /** @test */ public function requestsWithNonEmptyBodyJustFallbackToNextMiddleware(): void { - $request = $this->prophesize(ServerRequestInterface::class); - $request->getMethod()->willReturn('POST'); - $request->getParsedBody()->willReturn(['foo' => 'bar']); + $request = $this->createMock(ServerRequestInterface::class); + $request->method('getMethod')->willReturn('POST'); + $request->method('getParsedBody')->willReturn(['foo' => 'bar']); - self::assertHandlingRequestJustFallsBackToNext($request); + $this->assertHandlingRequestJustFallsBackToNext($request); } - private function assertHandlingRequestJustFallsBackToNext(ProphecyInterface $requestMock): void + private function assertHandlingRequestJustFallsBackToNext(MockObject & ServerRequestInterface $request): void { - $getContentType = $requestMock->getHeaderLine('Content-type')->willReturn(''); - $request = $requestMock->reveal(); + $request->expects($this->never())->method('getHeaderLine'); - $nextHandler = $this->prophesize(RequestHandlerInterface::class); - $handle = $nextHandler->handle($request)->willReturn(new Response()); + $nextHandler = $this->createMock(RequestHandlerInterface::class); + $nextHandler->expects($this->once())->method('handle')->with($request)->willReturn(new Response()); - $this->middleware->process($request, $nextHandler->reveal()); - - $handle->shouldHaveBeenCalledOnce(); - $getContentType->shouldNotHaveBeenCalled(); + $this->middleware->process($request, $nextHandler); } /** @test */ @@ -80,12 +70,11 @@ class BodyParserMiddlewareTest extends TestCase $body->write('{"foo": "bar", "bar": ["one", 5]}'); $request = (new ServerRequest())->withMethod('PUT') ->withBody($body); - $delegate = $this->prophesize(RequestHandlerInterface::class); - $process = $delegate->handle(Argument::type(ServerRequestInterface::class))->will( - function (array $args) use ($test) { - /** @var ServerRequestInterface $req */ - $req = array_shift($args); - + $handler = $this->createMock(RequestHandlerInterface::class); + $handler->expects($this->once())->method('handle')->with( + $this->isInstanceOf(ServerRequestInterface::class), + )->willReturnCallback( + function (ServerRequestInterface $req) use ($test) { $test->assertEquals([ 'foo' => 'bar', 'bar' => ['one', 5], @@ -95,8 +84,6 @@ class BodyParserMiddlewareTest extends TestCase }, ); - $this->middleware->process($request, $delegate->reveal()); - - $process->shouldHaveBeenCalledOnce(); + $this->middleware->process($request, $handler); } } diff --git a/module/Rest/test/Middleware/CrossDomainMiddlewareTest.php b/module/Rest/test/Middleware/CrossDomainMiddlewareTest.php index 286652bf..e9b294da 100644 --- a/module/Rest/test/Middleware/CrossDomainMiddlewareTest.php +++ b/module/Rest/test/Middleware/CrossDomainMiddlewareTest.php @@ -6,33 +6,29 @@ namespace ShlinkioTest\Shlink\Rest\Middleware; use Laminas\Diactoros\Response; use Laminas\Diactoros\ServerRequest; +use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; -use Prophecy\Argument; -use Prophecy\PhpUnit\ProphecyTrait; -use Prophecy\Prophecy\ObjectProphecy; use Psr\Http\Server\RequestHandlerInterface; use Shlinkio\Shlink\Rest\Middleware\CrossDomainMiddleware; class CrossDomainMiddlewareTest extends TestCase { - use ProphecyTrait; - private CrossDomainMiddleware $middleware; - private ObjectProphecy $handler; + private MockObject $handler; protected function setUp(): void { $this->middleware = new CrossDomainMiddleware(['max_age' => 1000]); - $this->handler = $this->prophesize(RequestHandlerInterface::class); + $this->handler = $this->createMock(RequestHandlerInterface::class); } /** @test */ public function nonCrossDomainRequestsAreNotAffected(): void { $originalResponse = (new Response())->withStatus(404); - $this->handler->handle(Argument::any())->willReturn($originalResponse)->shouldBeCalledOnce(); + $this->handler->expects($this->once())->method('handle')->willReturn($originalResponse); - $response = $this->middleware->process(new ServerRequest(), $this->handler->reveal()); + $response = $this->middleware->process(new ServerRequest(), $this->handler); $headers = $response->getHeaders(); self::assertSame($originalResponse, $response); @@ -47,12 +43,9 @@ class CrossDomainMiddlewareTest extends TestCase public function anyRequestIncludesTheAllowAccessHeader(): void { $originalResponse = new Response(); - $this->handler->handle(Argument::any())->willReturn($originalResponse)->shouldBeCalledOnce(); + $this->handler->expects($this->once())->method('handle')->willReturn($originalResponse); - $response = $this->middleware->process( - (new ServerRequest())->withHeader('Origin', 'local'), - $this->handler->reveal(), - ); + $response = $this->middleware->process((new ServerRequest())->withHeader('Origin', 'local'), $this->handler); self::assertNotSame($originalResponse, $response); $headers = $response->getHeaders(); @@ -71,9 +64,9 @@ class CrossDomainMiddlewareTest extends TestCase ->withMethod('OPTIONS') ->withHeader('Origin', 'local') ->withHeader('Access-Control-Request-Headers', 'foo, bar, baz'); - $this->handler->handle(Argument::any())->willReturn($originalResponse)->shouldBeCalledOnce(); + $this->handler->expects($this->once())->method('handle')->willReturn($originalResponse); - $response = $this->middleware->process($request, $this->handler->reveal()); + $response = $this->middleware->process($request, $this->handler); self::assertNotSame($originalResponse, $response); $headers = $response->getHeaders(); @@ -99,9 +92,9 @@ class CrossDomainMiddlewareTest extends TestCase } $request = (new ServerRequest())->withHeader('Origin', 'local') ->withMethod('OPTIONS'); - $this->handler->handle(Argument::any())->willReturn($originalResponse)->shouldBeCalledOnce(); + $this->handler->expects($this->once())->method('handle')->willReturn($originalResponse); - $response = $this->middleware->process($request, $this->handler->reveal()); + $response = $this->middleware->process($request, $this->handler); self::assertEquals($response->getHeaderLine('Access-Control-Allow-Methods'), $expectedAllowedMethods); self::assertEquals(204, $response->getStatusCode()); @@ -126,9 +119,9 @@ class CrossDomainMiddlewareTest extends TestCase $originalResponse = (new Response())->withStatus($status); $request = (new ServerRequest())->withMethod($method) ->withHeader('Origin', 'local'); - $this->handler->handle(Argument::any())->willReturn($originalResponse)->shouldBeCalledOnce(); + $this->handler->expects($this->once())->method('handle')->willReturn($originalResponse); - $response = $this->middleware->process($request, $this->handler->reveal()); + $response = $this->middleware->process($request, $this->handler); self::assertEquals($expectedStatus, $response->getStatusCode()); } diff --git a/module/Rest/test/Middleware/ErrorHandler/BackwardsCompatibleProblemDetailsHandlerTest.php b/module/Rest/test/Middleware/ErrorHandler/BackwardsCompatibleProblemDetailsHandlerTest.php index 00dddb2f..ab468803 100644 --- a/module/Rest/test/Middleware/ErrorHandler/BackwardsCompatibleProblemDetailsHandlerTest.php +++ b/module/Rest/test/Middleware/ErrorHandler/BackwardsCompatibleProblemDetailsHandlerTest.php @@ -6,7 +6,6 @@ namespace ShlinkioTest\Shlink\Rest\Middleware\ErrorHandler; use Laminas\Diactoros\ServerRequestFactory; use PHPUnit\Framework\TestCase; -use Prophecy\PhpUnit\ProphecyTrait; use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Server\RequestHandlerInterface; use Shlinkio\Shlink\Core\Exception\ValidationException; @@ -16,8 +15,6 @@ use Throwable; class BackwardsCompatibleProblemDetailsHandlerTest extends TestCase { - use ProphecyTrait; - private BackwardsCompatibleProblemDetailsHandler $handler; protected function setUp(): void @@ -34,13 +31,12 @@ class BackwardsCompatibleProblemDetailsHandlerTest extends TestCase Throwable $thrownException, string $expectedException, ): void { - $handler = $this->prophesize(RequestHandlerInterface::class); - $handle = $handler->handle($request)->willThrow($thrownException); + $handler = $this->createMock(RequestHandlerInterface::class); + $handler->expects($this->once())->method('handle')->with($request)->willThrowException($thrownException); $this->expectException($expectedException); - $handle->shouldBeCalledOnce(); - $this->handler->process($request, $handler->reveal()); + $this->handler->process($request, $handler); } public function provideExceptions(): iterable diff --git a/module/Rest/test/Middleware/Mercure/NotConfiguredMercureErrorHandlerTest.php b/module/Rest/test/Middleware/Mercure/NotConfiguredMercureErrorHandlerTest.php index 138c01f0..9fe595ec 100644 --- a/module/Rest/test/Middleware/Mercure/NotConfiguredMercureErrorHandlerTest.php +++ b/module/Rest/test/Middleware/Mercure/NotConfiguredMercureErrorHandlerTest.php @@ -7,10 +7,8 @@ namespace ShlinkioTest\Shlink\Rest\Middleware\Mercure; use Laminas\Diactoros\Response; use Laminas\Diactoros\ServerRequestFactory; use Mezzio\ProblemDetails\ProblemDetailsResponseFactory; +use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; -use Prophecy\Argument; -use Prophecy\PhpUnit\ProphecyTrait; -use Prophecy\Prophecy\ObjectProphecy; use Psr\Http\Server\RequestHandlerInterface; use Psr\Log\LoggerInterface; use Shlinkio\Shlink\Rest\Exception\MercureException; @@ -18,45 +16,40 @@ use Shlinkio\Shlink\Rest\Middleware\Mercure\NotConfiguredMercureErrorHandler; class NotConfiguredMercureErrorHandlerTest extends TestCase { - use ProphecyTrait; - private NotConfiguredMercureErrorHandler $middleware; - private ObjectProphecy $respFactory; - private ObjectProphecy $logger; - private ObjectProphecy $handler; + private MockObject $respFactory; + private MockObject $logger; + private MockObject $handler; protected function setUp(): void { - $this->respFactory = $this->prophesize(ProblemDetailsResponseFactory::class); - $this->logger = $this->prophesize(LoggerInterface::class); - $this->middleware = new NotConfiguredMercureErrorHandler($this->respFactory->reveal(), $this->logger->reveal()); - $this->handler = $this->prophesize(RequestHandlerInterface::class); + $this->respFactory = $this->createMock(ProblemDetailsResponseFactory::class); + $this->logger = $this->createMock(LoggerInterface::class); + $this->middleware = new NotConfiguredMercureErrorHandler($this->respFactory, $this->logger); + $this->handler = $this->createMock(RequestHandlerInterface::class); } /** @test */ public function requestHandlerIsInvokedWhenNotErrorOccurs(): void { $req = ServerRequestFactory::fromGlobals(); - $handle = $this->handler->handle($req)->willReturn(new Response()); + $this->handler->expects($this->once())->method('handle')->with($req)->willReturn(new Response()); + $this->respFactory->expects($this->never())->method('createResponseFromThrowable'); + $this->logger->expects($this->never())->method('warning'); - $this->middleware->process($req, $this->handler->reveal()); - - $handle->shouldHaveBeenCalledOnce(); - $this->logger->warning(Argument::cetera())->shouldNotHaveBeenCalled(); - $this->respFactory->createResponseFromThrowable(Argument::cetera())->shouldNotHaveBeenCalled(); + $this->middleware->process($req, $this->handler); } /** @test */ public function exceptionIsParsedToResponse(): void { $req = ServerRequestFactory::fromGlobals(); - $handle = $this->handler->handle($req)->willThrow(MercureException::mercureNotConfigured()); - $createResp = $this->respFactory->createResponseFromThrowable(Argument::cetera())->willReturn(new Response()); + $this->handler->expects($this->once())->method('handle')->with($req)->willThrowException( + MercureException::mercureNotConfigured(), + ); + $this->respFactory->expects($this->once())->method('createResponseFromThrowable')->willReturn(new Response()); + $this->logger->expects($this->once())->method('warning'); - $this->middleware->process($req, $this->handler->reveal()); - - $handle->shouldHaveBeenCalledOnce(); - $createResp->shouldHaveBeenCalledOnce(); - $this->logger->warning(Argument::cetera())->shouldHaveBeenCalledOnce(); + $this->middleware->process($req, $this->handler); } } diff --git a/module/Rest/test/Middleware/ShortUrl/CreateShortUrlContentNegotiationMiddlewareTest.php b/module/Rest/test/Middleware/ShortUrl/CreateShortUrlContentNegotiationMiddlewareTest.php index b77d79a9..1e56d690 100644 --- a/module/Rest/test/Middleware/ShortUrl/CreateShortUrlContentNegotiationMiddlewareTest.php +++ b/module/Rest/test/Middleware/ShortUrl/CreateShortUrlContentNegotiationMiddlewareTest.php @@ -7,34 +7,32 @@ namespace ShlinkioTest\Shlink\Rest\Middleware\ShortUrl; use Laminas\Diactoros\Response; use Laminas\Diactoros\Response\JsonResponse; use Laminas\Diactoros\ServerRequest; +use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; -use Prophecy\Argument; -use Prophecy\PhpUnit\ProphecyTrait; -use Prophecy\Prophecy\ObjectProphecy; use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Server\RequestHandlerInterface; use Shlinkio\Shlink\Rest\Middleware\ShortUrl\CreateShortUrlContentNegotiationMiddleware; class CreateShortUrlContentNegotiationMiddlewareTest extends TestCase { - use ProphecyTrait; - private CreateShortUrlContentNegotiationMiddleware $middleware; - private ObjectProphecy $requestHandler; + private MockObject $requestHandler; protected function setUp(): void { $this->middleware = new CreateShortUrlContentNegotiationMiddleware(); - $this->requestHandler = $this->prophesize(RequestHandlerInterface::class); + $this->requestHandler = $this->createMock(RequestHandlerInterface::class); } /** @test */ public function whenNoJsonResponseIsReturnedNoFurtherOperationsArePerformed(): void { $expectedResp = new Response(); - $this->requestHandler->handle(Argument::type(ServerRequestInterface::class))->willReturn($expectedResp); + $this->requestHandler->method('handle')->with($this->isInstanceOf(ServerRequestInterface::class))->willReturn( + $expectedResp, + ); - $resp = $this->middleware->process(new ServerRequest(), $this->requestHandler->reveal()); + $resp = $this->middleware->process(new ServerRequest(), $this->requestHandler); self::assertSame($expectedResp, $resp); } @@ -51,14 +49,13 @@ class CreateShortUrlContentNegotiationMiddlewareTest extends TestCase $request = $request->withHeader('Accept', $accept); } - $handle = $this->requestHandler->handle(Argument::type(ServerRequestInterface::class))->willReturn( - new JsonResponse(['shortUrl' => 'http://doma.in/foo']), - ); + $this->requestHandler->expects($this->once())->method('handle')->with( + $this->isInstanceOf(ServerRequestInterface::class), + )->willReturn(new JsonResponse(['shortUrl' => 'http://doma.in/foo'])); - $response = $this->middleware->process($request, $this->requestHandler->reveal()); + $response = $this->middleware->process($request, $this->requestHandler); self::assertEquals($expectedContentType, $response->getHeaderLine('Content-type')); - $handle->shouldHaveBeenCalled(); } public function provideData(): iterable @@ -82,14 +79,13 @@ class CreateShortUrlContentNegotiationMiddlewareTest extends TestCase { $request = (new ServerRequest())->withQueryParams(['format' => 'txt']); - $handle = $this->requestHandler->handle(Argument::type(ServerRequestInterface::class))->willReturn( - new JsonResponse($json), - ); + $this->requestHandler->expects($this->once())->method('handle')->with( + $this->isInstanceOf(ServerRequestInterface::class), + )->willReturn(new JsonResponse($json)); - $response = $this->middleware->process($request, $this->requestHandler->reveal()); + $response = $this->middleware->process($request, $this->requestHandler); self::assertEquals($expectedBody, (string) $response->getBody()); - $handle->shouldHaveBeenCalled(); } public function provideTextBodies(): iterable diff --git a/module/Rest/test/Middleware/ShortUrl/DefaultShortCodesLengthMiddlewareTest.php b/module/Rest/test/Middleware/ShortUrl/DefaultShortCodesLengthMiddlewareTest.php index 7f61830c..f7a647b1 100644 --- a/module/Rest/test/Middleware/ShortUrl/DefaultShortCodesLengthMiddlewareTest.php +++ b/module/Rest/test/Middleware/ShortUrl/DefaultShortCodesLengthMiddlewareTest.php @@ -7,10 +7,8 @@ namespace ShlinkioTest\Shlink\Rest\Middleware\ShortUrl; use Laminas\Diactoros\Response; use Laminas\Diactoros\ServerRequestFactory; use PHPUnit\Framework\Assert; +use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; -use Prophecy\Argument; -use Prophecy\PhpUnit\ProphecyTrait; -use Prophecy\Prophecy\ObjectProphecy; use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Server\RequestHandlerInterface; use Shlinkio\Shlink\Core\ShortUrl\Model\Validation\ShortUrlInputFilter; @@ -18,14 +16,12 @@ use Shlinkio\Shlink\Rest\Middleware\ShortUrl\DefaultShortCodesLengthMiddleware; class DefaultShortCodesLengthMiddlewareTest extends TestCase { - use ProphecyTrait; - private DefaultShortCodesLengthMiddleware $middleware; - private ObjectProphecy $handler; + private MockObject $handler; protected function setUp(): void { - $this->handler = $this->prophesize(RequestHandlerInterface::class); + $this->handler = $this->createMock(RequestHandlerInterface::class); $this->middleware = new DefaultShortCodesLengthMiddleware(8); } @@ -36,17 +32,17 @@ class DefaultShortCodesLengthMiddlewareTest extends TestCase public function defaultValueIsInjectedInBodyWhenNotProvided(array $body, int $expectedLength): void { $request = ServerRequestFactory::fromGlobals()->withParsedBody($body); - $handle = $this->handler->handle(Argument::that(function (ServerRequestInterface $req) use ($expectedLength) { - $parsedBody = $req->getParsedBody(); - Assert::assertArrayHasKey(ShortUrlInputFilter::SHORT_CODE_LENGTH, $parsedBody); - Assert::assertEquals($expectedLength, $parsedBody[ShortUrlInputFilter::SHORT_CODE_LENGTH]); + $this->handler->expects($this->once())->method('handle')->with($this->callback( + function (ServerRequestInterface $req) use ($expectedLength) { + $parsedBody = $req->getParsedBody(); + Assert::assertArrayHasKey(ShortUrlInputFilter::SHORT_CODE_LENGTH, $parsedBody); + Assert::assertEquals($expectedLength, $parsedBody[ShortUrlInputFilter::SHORT_CODE_LENGTH]); - return $req; - }))->willReturn(new Response()); + return true; + }, + ))->willReturn(new Response()); - $this->middleware->process($request, $this->handler->reveal()); - - $handle->shouldHaveBeenCalledOnce(); + $this->middleware->process($request, $this->handler); } public function provideBodies(): iterable diff --git a/module/Rest/test/Middleware/ShortUrl/DropDefaultDomainFromRequestMiddlewareTest.php b/module/Rest/test/Middleware/ShortUrl/DropDefaultDomainFromRequestMiddlewareTest.php index 9418a16a..eb018ad3 100644 --- a/module/Rest/test/Middleware/ShortUrl/DropDefaultDomainFromRequestMiddlewareTest.php +++ b/module/Rest/test/Middleware/ShortUrl/DropDefaultDomainFromRequestMiddlewareTest.php @@ -7,24 +7,20 @@ namespace ShlinkioTest\Shlink\Rest\Middleware\ShortUrl; use Laminas\Diactoros\Response; use Laminas\Diactoros\ServerRequestFactory; use PHPUnit\Framework\Assert; +use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; -use Prophecy\Argument; -use Prophecy\PhpUnit\ProphecyTrait; -use Prophecy\Prophecy\ObjectProphecy; use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Server\RequestHandlerInterface; use Shlinkio\Shlink\Rest\Middleware\ShortUrl\DropDefaultDomainFromRequestMiddleware; class DropDefaultDomainFromRequestMiddlewareTest extends TestCase { - use ProphecyTrait; - private DropDefaultDomainFromRequestMiddleware $middleware; - private ObjectProphecy $next; + private MockObject $next; protected function setUp(): void { - $this->next = $this->prophesize(RequestHandlerInterface::class); + $this->next = $this->createMock(RequestHandlerInterface::class); $this->middleware = new DropDefaultDomainFromRequestMiddleware('doma.in'); } @@ -36,15 +32,15 @@ class DropDefaultDomainFromRequestMiddlewareTest extends TestCase { $req = ServerRequestFactory::fromGlobals()->withQueryParams($providedPayload)->withParsedBody($providedPayload); - $handle = $this->next->handle(Argument::that(function (ServerRequestInterface $request) use ($expectedPayload) { - Assert::assertEquals($expectedPayload, $request->getQueryParams()); - Assert::assertEquals($expectedPayload, $request->getParsedBody()); - return $request; - }))->willReturn(new Response()); + $this->next->expects($this->once())->method('handle')->with($this->callback( + function (ServerRequestInterface $request) use ($expectedPayload) { + Assert::assertEquals($expectedPayload, $request->getQueryParams()); + Assert::assertEquals($expectedPayload, $request->getParsedBody()); + return true; + }, + ))->willReturn(new Response()); - $this->middleware->process($req, $this->next->reveal()); - - $handle->shouldHaveBeenCalledOnce(); + $this->middleware->process($req, $this->next); } public function provideQueryParams(): iterable diff --git a/module/Rest/test/Middleware/ShortUrl/OverrideDomainMiddlewareTest.php b/module/Rest/test/Middleware/ShortUrl/OverrideDomainMiddlewareTest.php index 4bf469a4..f4f0b4d1 100644 --- a/module/Rest/test/Middleware/ShortUrl/OverrideDomainMiddlewareTest.php +++ b/module/Rest/test/Middleware/ShortUrl/OverrideDomainMiddlewareTest.php @@ -7,10 +7,8 @@ namespace ShlinkioTest\Shlink\Rest\Middleware\ShortUrl; use Laminas\Diactoros\Response; use Laminas\Diactoros\ServerRequestFactory; use PHPUnit\Framework\Assert; +use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; -use Prophecy\Argument; -use Prophecy\PhpUnit\ProphecyTrait; -use Prophecy\Prophecy\ObjectProphecy; use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Server\RequestHandlerInterface; use Shlinkio\Shlink\Core\Domain\DomainServiceInterface; @@ -22,20 +20,18 @@ use Shlinkio\Shlink\Rest\Middleware\ShortUrl\OverrideDomainMiddleware; class OverrideDomainMiddlewareTest extends TestCase { - use ProphecyTrait; - private OverrideDomainMiddleware $middleware; - private ObjectProphecy $domainService; - private ObjectProphecy $apiKey; - private ObjectProphecy $handler; + private MockObject $domainService; + private MockObject $apiKey; + private MockObject $handler; protected function setUp(): void { - $this->apiKey = $this->prophesize(ApiKey::class); - $this->handler = $this->prophesize(RequestHandlerInterface::class); + $this->apiKey = $this->createMock(ApiKey::class); + $this->handler = $this->createMock(RequestHandlerInterface::class); - $this->domainService = $this->prophesize(DomainServiceInterface::class); - $this->middleware = new OverrideDomainMiddleware($this->domainService->reveal()); + $this->domainService = $this->createMock(DomainServiceInterface::class); + $this->middleware = new OverrideDomainMiddleware($this->domainService); } /** @test */ @@ -43,16 +39,13 @@ class OverrideDomainMiddlewareTest extends TestCase { $request = $this->requestWithApiKey(); $response = new Response(); - $hasRole = $this->apiKey->hasRole(Role::DOMAIN_SPECIFIC)->willReturn(false); - $handle = $this->handler->handle($request)->willReturn($response); - $getDomain = $this->domainService->getDomain(Argument::cetera()); + $this->apiKey->expects($this->once())->method('hasRole')->with(Role::DOMAIN_SPECIFIC)->willReturn(false); + $this->handler->expects($this->once())->method('handle')->with($request)->willReturn($response); + $this->domainService->expects($this->never())->method('getDomain'); - $result = $this->middleware->process($request, $this->handler->reveal()); + $result = $this->middleware->process($request, $this->handler); self::assertSame($response, $result); - $hasRole->shouldHaveBeenCalledOnce(); - $handle->shouldHaveBeenCalledOnce(); - $getDomain->shouldNotHaveBeenCalled(); } /** @@ -62,22 +55,19 @@ class OverrideDomainMiddlewareTest extends TestCase public function overwritesRequestBodyWhenMethodIsPost(Domain $domain, array $body, array $expectedBody): void { $request = $this->requestWithApiKey()->withMethod('POST')->withParsedBody($body); - $hasRole = $this->apiKey->hasRole(Role::DOMAIN_SPECIFIC)->willReturn(true); - $getRoleMeta = $this->apiKey->getRoleMeta(Role::DOMAIN_SPECIFIC)->willReturn(['domain_id' => '123']); - $getDomain = $this->domainService->getDomain('123')->willReturn($domain); - $handle = $this->handler->handle(Argument::that( + $this->apiKey->expects($this->once())->method('hasRole')->with(Role::DOMAIN_SPECIFIC)->willReturn(true); + $this->apiKey->expects($this->once())->method('getRoleMeta')->with(Role::DOMAIN_SPECIFIC)->willReturn( + ['domain_id' => '123'], + ); + $this->domainService->expects($this->once())->method('getDomain')->with('123')->willReturn($domain); + $this->handler->expects($this->once())->method('handle')->with($this->callback( function (ServerRequestInterface $req) use ($expectedBody): bool { Assert::assertEquals($req->getParsedBody(), $expectedBody); return true; }, ))->willReturn(new Response()); - $this->middleware->process($request, $this->handler->reveal()); - - $hasRole->shouldHaveBeenCalledOnce(); - $getRoleMeta->shouldHaveBeenCalledOnce(); - $getDomain->shouldHaveBeenCalledOnce(); - $handle->shouldHaveBeenCalledOnce(); + $this->middleware->process($request, $this->handler); } public function provideBodies(): iterable @@ -112,22 +102,19 @@ class OverrideDomainMiddlewareTest extends TestCase { $domain = Domain::withAuthority('something.com'); $request = $this->requestWithApiKey()->withMethod($method); - $hasRole = $this->apiKey->hasRole(Role::DOMAIN_SPECIFIC)->willReturn(true); - $getRoleMeta = $this->apiKey->getRoleMeta(Role::DOMAIN_SPECIFIC)->willReturn(['domain_id' => '123']); - $getDomain = $this->domainService->getDomain('123')->willReturn($domain); - $handle = $this->handler->handle(Argument::that( + $this->apiKey->expects($this->once())->method('hasRole')->with(Role::DOMAIN_SPECIFIC)->willReturn(true); + $this->apiKey->expects($this->once())->method('getRoleMeta')->with(Role::DOMAIN_SPECIFIC)->willReturn( + ['domain_id' => '123'], + ); + $this->domainService->expects($this->once())->method('getDomain')->with('123')->willReturn($domain); + $this->handler->expects($this->once())->method('handle')->with($this->callback( function (ServerRequestInterface $req): bool { Assert::assertEquals($req->getAttribute(ShortUrlInputFilter::DOMAIN), 'something.com'); return true; }, ))->willReturn(new Response()); - $this->middleware->process($request, $this->handler->reveal()); - - $hasRole->shouldHaveBeenCalledOnce(); - $getRoleMeta->shouldHaveBeenCalledOnce(); - $getDomain->shouldHaveBeenCalledOnce(); - $handle->shouldHaveBeenCalledOnce(); + $this->middleware->process($request, $this->handler); } public function provideMethods(): iterable @@ -140,6 +127,6 @@ class OverrideDomainMiddlewareTest extends TestCase private function requestWithApiKey(): ServerRequestInterface { - return ServerRequestFactory::fromGlobals()->withAttribute(ApiKey::class, $this->apiKey->reveal()); + return ServerRequestFactory::fromGlobals()->withAttribute(ApiKey::class, $this->apiKey); } } diff --git a/module/Rest/test/Service/ApiKeyServiceTest.php b/module/Rest/test/Service/ApiKeyServiceTest.php index 66bd4c28..9336da9e 100644 --- a/module/Rest/test/Service/ApiKeyServiceTest.php +++ b/module/Rest/test/Service/ApiKeyServiceTest.php @@ -7,10 +7,8 @@ namespace ShlinkioTest\Shlink\Rest\Service; use Cake\Chronos\Chronos; use Doctrine\ORM\EntityManager; use Doctrine\ORM\EntityRepository; +use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; -use Prophecy\Argument; -use Prophecy\PhpUnit\ProphecyTrait; -use Prophecy\Prophecy\ObjectProphecy; use Shlinkio\Shlink\Common\Exception\InvalidArgumentException; use Shlinkio\Shlink\Core\Domain\Entity\Domain; use Shlinkio\Shlink\Rest\ApiKey\Model\ApiKeyMeta; @@ -20,15 +18,15 @@ use Shlinkio\Shlink\Rest\Service\ApiKeyService; class ApiKeyServiceTest extends TestCase { - use ProphecyTrait; - private ApiKeyService $service; - private ObjectProphecy $em; + private MockObject $em; + private MockObject $repo; protected function setUp(): void { - $this->em = $this->prophesize(EntityManager::class); - $this->service = new ApiKeyService($this->em->reveal()); + $this->em = $this->createMock(EntityManager::class); + $this->repo = $this->createMock(EntityRepository::class); + $this->service = new ApiKeyService($this->em); } /** @@ -38,8 +36,8 @@ class ApiKeyServiceTest extends TestCase */ public function apiKeyIsProperlyCreated(?Chronos $date, ?string $name, array $roles): void { - $this->em->flush()->shouldBeCalledOnce(); - $this->em->persist(Argument::type(ApiKey::class))->shouldBeCalledOnce(); + $this->em->expects($this->once())->method('flush'); + $this->em->expects($this->once())->method('persist')->with($this->isInstanceOf(ApiKey::class)); $key = $this->service->create($date, $name, ...$roles); @@ -69,10 +67,8 @@ class ApiKeyServiceTest extends TestCase */ public function checkReturnsFalseForInvalidApiKeys(?ApiKey $invalidKey): void { - $repo = $this->prophesize(EntityRepository::class); - $repo->findOneBy(['key' => '12345'])->willReturn($invalidKey) - ->shouldBeCalledOnce(); - $this->em->getRepository(ApiKey::class)->willReturn($repo->reveal()); + $this->repo->expects($this->once())->method('findOneBy')->with(['key' => '12345'])->willReturn($invalidKey); + $this->em->method('getRepository')->with(ApiKey::class)->willReturn($this->repo); $result = $this->service->check('12345'); @@ -92,10 +88,8 @@ class ApiKeyServiceTest extends TestCase { $apiKey = ApiKey::create(); - $repo = $this->prophesize(EntityRepository::class); - $repo->findOneBy(['key' => '12345'])->willReturn($apiKey) - ->shouldBeCalledOnce(); - $this->em->getRepository(ApiKey::class)->willReturn($repo->reveal()); + $this->repo->expects($this->once())->method('findOneBy')->with(['key' => '12345'])->willReturn($apiKey); + $this->em->method('getRepository')->with(ApiKey::class)->willReturn($this->repo); $result = $this->service->check('12345'); @@ -106,10 +100,8 @@ class ApiKeyServiceTest extends TestCase /** @test */ public function disableThrowsExceptionWhenNoApiKeyIsFound(): void { - $repo = $this->prophesize(EntityRepository::class); - $repo->findOneBy(['key' => '12345'])->willReturn(null) - ->shouldBeCalledOnce(); - $this->em->getRepository(ApiKey::class)->willReturn($repo->reveal()); + $this->repo->expects($this->once())->method('findOneBy')->with(['key' => '12345'])->willReturn(null); + $this->em->method('getRepository')->with(ApiKey::class)->willReturn($this->repo); $this->expectException(InvalidArgumentException::class); @@ -120,12 +112,9 @@ class ApiKeyServiceTest extends TestCase public function disableReturnsDisabledApiKeyWhenFound(): void { $key = ApiKey::create(); - $repo = $this->prophesize(EntityRepository::class); - $repo->findOneBy(['key' => '12345'])->willReturn($key) - ->shouldBeCalledOnce(); - $this->em->getRepository(ApiKey::class)->willReturn($repo->reveal()); - - $this->em->flush()->shouldBeCalledOnce(); + $this->repo->expects($this->once())->method('findOneBy')->with(['key' => '12345'])->willReturn($key); + $this->em->method('getRepository')->with(ApiKey::class)->willReturn($this->repo); + $this->em->expects($this->once())->method('flush'); self::assertTrue($key->isEnabled()); $returnedKey = $this->service->disable('12345'); @@ -138,10 +127,8 @@ class ApiKeyServiceTest extends TestCase { $expectedApiKeys = [ApiKey::create(), ApiKey::create(), ApiKey::create()]; - $repo = $this->prophesize(EntityRepository::class); - $repo->findBy([])->willReturn($expectedApiKeys) - ->shouldBeCalledOnce(); - $this->em->getRepository(ApiKey::class)->willReturn($repo->reveal()); + $this->repo->expects($this->once())->method('findBy')->with([])->willReturn($expectedApiKeys); + $this->em->method('getRepository')->with(ApiKey::class)->willReturn($this->repo); $result = $this->service->listKeys(); @@ -153,10 +140,8 @@ class ApiKeyServiceTest extends TestCase { $expectedApiKeys = [ApiKey::create(), ApiKey::create(), ApiKey::create()]; - $repo = $this->prophesize(EntityRepository::class); - $repo->findBy(['enabled' => true])->willReturn($expectedApiKeys) - ->shouldBeCalledOnce(); - $this->em->getRepository(ApiKey::class)->willReturn($repo->reveal()); + $this->repo->expects($this->once())->method('findBy')->with(['enabled' => true])->willReturn($expectedApiKeys); + $this->em->method('getRepository')->with(ApiKey::class)->willReturn($this->repo); $result = $this->service->listKeys(true);