diff --git a/module/Core/test/Importer/ImportedLinksProcessorTest.php b/module/Core/test/Importer/ImportedLinksProcessorTest.php
index 2ce93647..926901a9 100644
--- a/module/Core/test/Importer/ImportedLinksProcessorTest.php
+++ b/module/Core/test/Importer/ImportedLinksProcessorTest.php
@@ -7,10 +7,8 @@ namespace ShlinkioTest\Shlink\Core\Importer;
use Cake\Chronos\Chronos;
use Doctrine\Common\Collections\ArrayCollection;
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 RuntimeException;
use Shlinkio\Shlink\Core\Importer\ImportedLinksProcessor;
use Shlinkio\Shlink\Core\ShortUrl\Entity\ShortUrl;
@@ -23,6 +21,7 @@ use Shlinkio\Shlink\Importer\Model\ImportedShlinkUrl;
use Shlinkio\Shlink\Importer\Model\ImportedShlinkVisit;
use Shlinkio\Shlink\Importer\Params\ImportParams;
use Shlinkio\Shlink\Importer\Sources\ImportSource;
+use stdClass;
use Symfony\Component\Console\Style\StyleInterface;
use function count;
@@ -32,32 +31,30 @@ use function str_contains;
class ImportedLinksProcessorTest extends TestCase
{
- use ProphecyTrait;
-
private ImportedLinksProcessor $processor;
- private ObjectProphecy $em;
- private ObjectProphecy $shortCodeHelper;
- private ObjectProphecy $repo;
- private ObjectProphecy $io;
+ private MockObject $em;
+ private MockObject $shortCodeHelper;
+ private MockObject $repo;
+ private MockObject $io;
protected function setUp(): void
{
- $this->em = $this->prophesize(EntityManagerInterface::class);
- $this->repo = $this->prophesize(ShortUrlRepositoryInterface::class);
- $this->em->getRepository(ShortUrl::class)->willReturn($this->repo->reveal());
+ $this->em = $this->createMock(EntityManagerInterface::class);
+ $this->repo = $this->createMock(ShortUrlRepositoryInterface::class);
+ $this->em->method('getRepository')->with($this->equalTo(ShortUrl::class))->willReturn($this->repo);
- $this->shortCodeHelper = $this->prophesize(ShortCodeUniquenessHelperInterface::class);
- $batchHelper = $this->prophesize(DoctrineBatchHelperInterface::class);
- $batchHelper->wrapIterable(Argument::cetera())->willReturnArgument(0);
+ $this->shortCodeHelper = $this->createMock(ShortCodeUniquenessHelperInterface::class);
+ $batchHelper = $this->createMock(DoctrineBatchHelperInterface::class);
+ $batchHelper->method('wrapIterable')->willReturnArgument(0);
$this->processor = new ImportedLinksProcessor(
- $this->em->reveal(),
+ $this->em,
new SimpleShortUrlRelationResolver(),
- $this->shortCodeHelper->reveal(),
- $batchHelper->reveal(),
+ $this->shortCodeHelper,
+ $batchHelper,
);
- $this->io = $this->prophesize(StyleInterface::class);
+ $this->io = $this->createMock(StyleInterface::class);
}
/** @test */
@@ -70,16 +67,16 @@ class ImportedLinksProcessorTest extends TestCase
];
$expectedCalls = count($urls);
- $importedUrlExists = $this->repo->findOneByImportedUrl(Argument::cetera())->willReturn(null);
- $ensureUniqueness = $this->shortCodeHelper->ensureShortCodeUniqueness(Argument::cetera())->willReturn(true);
- $persist = $this->em->persist(Argument::type(ShortUrl::class));
+ $this->repo->expects($this->exactly($expectedCalls))->method('findOneByImportedUrl')->willReturn(null);
+ $this->shortCodeHelper->expects($this->exactly($expectedCalls))
+ ->method('ensureShortCodeUniqueness')
+ ->willReturn(true);
+ $this->em->expects($this->exactly($expectedCalls))->method('persist')->with(
+ $this->isInstanceOf(ShortUrl::class),
+ );
+ $this->io->expects($this->exactly($expectedCalls))->method('text')->with($this->isType('string'));
- $this->processor->process($this->io->reveal(), $urls, $this->buildParams());
-
- $importedUrlExists->shouldHaveBeenCalledTimes($expectedCalls);
- $ensureUniqueness->shouldHaveBeenCalledTimes($expectedCalls);
- $persist->shouldHaveBeenCalledTimes($expectedCalls);
- $this->io->text(Argument::type('string'))->shouldHaveBeenCalledTimes($expectedCalls);
+ $this->processor->process($this->io, $urls, $this->buildParams());
}
/** @test */
@@ -91,26 +88,21 @@ class ImportedLinksProcessorTest extends TestCase
new ImportedShlinkUrl(ImportSource::BITLY, 'baz', [], Chronos::now(), null, 'baz', null),
];
- $importedUrlExists = $this->repo->findOneByImportedUrl(Argument::cetera())->willReturn(null);
- $ensureUniqueness = $this->shortCodeHelper->ensureShortCodeUniqueness(Argument::cetera())->willReturn(true);
- $persist = $this->em->persist(Argument::type(ShortUrl::class))->will(function (array $args): void {
- /** @var ShortUrl $shortUrl */
- [$shortUrl] = $args;
-
+ $this->repo->expects($this->exactly(3))->method('findOneByImportedUrl')->willReturn(null);
+ $this->shortCodeHelper->expects($this->exactly(3))->method('ensureShortCodeUniqueness')->willReturn(true);
+ $this->em->expects($this->exactly(3))->method('persist')->with(
+ $this->isInstanceOf(ShortUrl::class),
+ )->willReturnCallback(function (ShortUrl $shortUrl): void {
if ($shortUrl->getShortCode() === 'baz') {
throw new RuntimeException('Whatever error');
}
});
+ $textCalls = $this->setUpIoText('Skipped. Reason: Whatever error', 'Imported');
- $this->processor->process($this->io->reveal(), $urls, $this->buildParams());
+ $this->processor->process($this->io, $urls, $this->buildParams());
- $importedUrlExists->shouldHaveBeenCalledTimes(3);
- $ensureUniqueness->shouldHaveBeenCalledTimes(3);
- $persist->shouldHaveBeenCalledTimes(3);
- $this->io->text(Argument::containingString('Imported'))->shouldHaveBeenCalledTimes(2);
- $this->io->text(
- Argument::containingString('Skipped. Reason: Whatever error'),
- )->shouldHaveBeenCalledOnce();
+ self::assertEquals(2, $textCalls->importedCount);
+ self::assertEquals(1, $textCalls->skippedCount);
}
/** @test */
@@ -124,24 +116,18 @@ class ImportedLinksProcessorTest extends TestCase
new ImportedShlinkUrl(ImportSource::BITLY, 'baz3', [], Chronos::now(), null, 'baz3', null),
];
- $importedUrlExists = $this->repo->findOneByImportedUrl(Argument::cetera())->will(
- function (array $args): ?ShortUrl {
- /** @var ImportedShlinkUrl $url */
- [$url] = $args;
-
- return contains(['foo', 'baz2', 'baz3'], $url->longUrl) ? ShortUrl::fromImport($url, true) : null;
- },
+ $this->repo->expects($this->exactly(count($urls)))->method('findOneByImportedUrl')->willReturnCallback(
+ fn (ImportedShlinkUrl $url): ?ShortUrl
+ => contains(['foo', 'baz2', 'baz3'], $url->longUrl) ? ShortUrl::fromImport($url, true) : null,
);
- $ensureUniqueness = $this->shortCodeHelper->ensureShortCodeUniqueness(Argument::cetera())->willReturn(true);
- $persist = $this->em->persist(Argument::type(ShortUrl::class));
+ $this->shortCodeHelper->expects($this->exactly(2))->method('ensureShortCodeUniqueness')->willReturn(true);
+ $this->em->expects($this->exactly(2))->method('persist')->with($this->isInstanceOf(ShortUrl::class));
+ $textCalls = $this->setUpIoText();
- $this->processor->process($this->io->reveal(), $urls, $this->buildParams());
+ $this->processor->process($this->io, $urls, $this->buildParams());
- $importedUrlExists->shouldHaveBeenCalledTimes(count($urls));
- $ensureUniqueness->shouldHaveBeenCalledTimes(2);
- $persist->shouldHaveBeenCalledTimes(2);
- $this->io->text(Argument::containingString('Skipped'))->shouldHaveBeenCalledTimes(3);
- $this->io->text(Argument::containingString('Imported'))->shouldHaveBeenCalledTimes(2);
+ self::assertEquals(2, $textCalls->importedCount);
+ self::assertEquals(3, $textCalls->skippedCount);
}
/** @test */
@@ -155,32 +141,20 @@ class ImportedLinksProcessorTest extends TestCase
new ImportedShlinkUrl(ImportSource::BITLY, 'baz3', [], Chronos::now(), null, 'baz3', 'bar'),
];
- $importedUrlExists = $this->repo->findOneByImportedUrl(Argument::cetera())->willReturn(null);
- $failingEnsureUniqueness = $this->shortCodeHelper->ensureShortCodeUniqueness(
- Argument::any(),
- true,
- )->willReturn(false);
- $successEnsureUniqueness = $this->shortCodeHelper->ensureShortCodeUniqueness(
- Argument::any(),
- false,
- )->willReturn(true);
- $choice = $this->io->choice(Argument::cetera())->will(function (array $args) {
- /** @var ImportedShlinkUrl $url */
- [$question] = $args;
-
+ $this->repo->expects($this->exactly(count($urls)))->method('findOneByImportedUrl')->willReturn(null);
+ $this->shortCodeHelper->expects($this->exactly(7))->method('ensureShortCodeUniqueness')->willReturnCallback(
+ fn ($_, bool $hasCustomSlug) => ! $hasCustomSlug,
+ );
+ $this->em->expects($this->exactly(2))->method('persist')->with($this->isInstanceOf(ShortUrl::class));
+ $this->io->expects($this->exactly(5))->method('choice')->willReturnCallback(function (string $question) {
return some(['foo', 'baz2', 'baz3'], fn (string $item) => str_contains($question, $item)) ? 'Skip' : '';
});
- $persist = $this->em->persist(Argument::type(ShortUrl::class));
+ $textCalls = $this->setUpIoText('Error');
- $this->processor->process($this->io->reveal(), $urls, $this->buildParams());
+ $this->processor->process($this->io, $urls, $this->buildParams());
- $importedUrlExists->shouldHaveBeenCalledTimes(count($urls));
- $failingEnsureUniqueness->shouldHaveBeenCalledTimes(5);
- $successEnsureUniqueness->shouldHaveBeenCalledTimes(2);
- $choice->shouldHaveBeenCalledTimes(5);
- $persist->shouldHaveBeenCalledTimes(2);
- $this->io->text(Argument::containingString('Error'))->shouldHaveBeenCalledTimes(3);
- $this->io->text(Argument::containingString('Imported'))->shouldHaveBeenCalledTimes(2);
+ self::assertEquals(2, $textCalls->importedCount);
+ self::assertEquals(3, $textCalls->skippedCount);
}
/**
@@ -193,18 +167,16 @@ class ImportedLinksProcessorTest extends TestCase
int $amountOfPersistedVisits,
?ShortUrl $foundShortUrl,
): void {
- $findExisting = $this->repo->findOneByImportedUrl(Argument::cetera())->willReturn($foundShortUrl);
- $ensureUniqueness = $this->shortCodeHelper->ensureShortCodeUniqueness(Argument::cetera())->willReturn(true);
- $persistUrl = $this->em->persist(Argument::type(ShortUrl::class));
- $persistVisits = $this->em->persist(Argument::type(Visit::class));
+ $this->repo->expects($this->once())->method('findOneByImportedUrl')->willReturn($foundShortUrl);
+ $this->shortCodeHelper->expects($this->exactly($foundShortUrl === null ? 1 : 0))
+ ->method('ensureShortCodeUniqueness')
+ ->willReturn(true);
+ $this->em->expects($this->exactly($amountOfPersistedVisits + ($foundShortUrl === null ? 1 : 0)))->method(
+ 'persist',
+ )->with($this->callback(fn (object $arg) => $arg instanceof ShortUrl || $arg instanceof Visit));
+ $this->io->expects($this->once())->method('text')->with($this->stringContains($expectedOutput));
- $this->processor->process($this->io->reveal(), [$importedUrl], $this->buildParams());
-
- $findExisting->shouldHaveBeenCalledOnce();
- $ensureUniqueness->shouldHaveBeenCalledTimes($foundShortUrl === null ? 1 : 0);
- $persistUrl->shouldHaveBeenCalledTimes($foundShortUrl === null ? 1 : 0);
- $persistVisits->shouldHaveBeenCalledTimes($amountOfPersistedVisits);
- $this->io->text(Argument::containingString($expectedOutput))->shouldHaveBeenCalledOnce();
+ $this->processor->process($this->io, [$importedUrl], $this->buildParams());
}
public function provideUrlsWithVisits(): iterable
@@ -251,4 +223,23 @@ class ImportedLinksProcessorTest extends TestCase
{
return ImportSource::BITLY->toParamsWithCallableMap(['import_short_codes' => static fn () => true]);
}
+
+ public function setUpIoText(string $skippedText = 'Skipped', string $importedText = 'Imported'): stdClass
+ {
+ $counts = new stdClass();
+ $counts->importedCount = 0;
+ $counts->skippedCount = 0;
+
+ $this->io->method('text')->willReturnCallback(
+ function (string $output) use ($counts, $skippedText, $importedText) {
+ if (str_contains($output, $skippedText)) {
+ $counts->skippedCount++;
+ } elseif (str_contains($output, $importedText)) {
+ $counts->importedCount++;
+ }
+ },
+ );
+
+ return $counts;
+ }
}