em = $this->createMock(EntityManagerInterface::class); $this->helper = new DoctrineBatchHelper($this->em); } #[Test, DataProvider('provideIterables')] public function entityManagerIsFlushedAndClearedTheExpectedAmountOfTimes( array $iterable, 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 } } public static function provideIterables(): iterable { yield [[], 100, 1]; yield [[1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 3, 4]; yield [[1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 11, 1]; } #[Test] public function transactionIsRolledBackWhenAnErrorOccurs(): void { $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); foreach ($wrappedIterable as $item) { // Iterable needs to be iterated for the logic to be invoked } } }