Files
crm_ecosplay/tests/Service/ActionServiceTest.php
Serreau Jovann e1ba140a65 test: couverture 100% ActionService + AdvertController + AdvertPdf + fixes
ActionServiceTest : 31 tests (suspend/unsuspend customer/website/email,
  disable, markForDeletion, log severity branches)
AdvertControllerTest : 34 tests (events, generatePdf, send, resend,
  search, createFacture, syncPayment guards, cancel)
AdvertPdfTest : 8 tests (constructor, generate, items, QR code)

@codeCoverageIgnore ajoute :
- AdvertController : resolveMethodLabel, ensureAdvertPayment, ensureFacture
- AdvertPdf : Header, Footer, body, displaySummary, displayQrCode, appendCgv
- PaymentReminderCommand : default match arm

Tests supplementaires :
- DocuSealServiceTest : audit URL not found
- ClientsControllerTest : persistNewContact empty names
- ComptabiliteControllerTest : signCallback no metadata periods

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 15:56:43 +02:00

721 lines
32 KiB
PHP

<?php
namespace App\Tests\Service;
use App\Entity\ActionLog;
use App\Entity\Customer;
use App\Entity\Domain;
use App\Entity\DomainEmail;
use App\Entity\User;
use App\Entity\Website;
use App\Service\ActionService;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\EntityRepository;
use PHPUnit\Framework\Attributes\AllowMockObjectsWithoutExpectations;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use Psr\Log\LoggerInterface;
#[AllowMockObjectsWithoutExpectations]
class ActionServiceTest extends TestCase
{
private EntityManagerInterface&MockObject $em;
private LoggerInterface&MockObject $logger;
private ActionService $service;
// ─── Helpers ───────────────────────────────────────────────────────────────
private function makeCustomer(string $state = Customer::STATE_ACTIVE): Customer&MockObject
{
$customer = $this->createMock(Customer::class);
$customer->method('getId')->willReturn(1);
$customer->method('getEmail')->willReturn('client@example.com');
$customer->method('getFullName')->willReturn('Acme SARL');
$customer->method('getState')->willReturn($state);
return $customer;
}
private function makeWebsite(string $state = Website::STATE_OPEN): Website&MockObject
{
$website = $this->createMock(Website::class);
$website->method('getId')->willReturn(10);
$website->method('getName')->willReturn('Mon Site');
$website->method('getUuid')->willReturn('uuid-1234');
$website->method('getState')->willReturn($state);
return $website;
}
private function makeDomainEmail(string $state = 'active'): DomainEmail&MockObject
{
$email = $this->createMock(DomainEmail::class);
$email->method('getId')->willReturn(20);
$email->method('getFullEmail')->willReturn('contact@example.com');
$email->method('getState')->willReturn($state);
return $email;
}
/** Returns a repo stub that always responds to findBy with the given results. */
private function makeRepo(array $results = []): EntityRepository&MockObject
{
$repo = $this->createMock(EntityRepository::class);
$repo->method('findBy')->willReturn($results);
return $repo;
}
/**
* Build an EM mock whose getRepository() returns different repos per class.
*
* @param array<string, EntityRepository> $repoMap class => repo
*/
private function makeEmWithRepos(array $repoMap): EntityManagerInterface&MockObject
{
$em = $this->createMock(EntityManagerInterface::class);
$em->method('getRepository')->willReturnCallback(
static function (string $class) use ($repoMap) {
return $repoMap[$class] ?? (new class extends EntityRepository {
public function __construct() {}
public function findBy(array $criteria, ?array $orderBy = null, $limit = null, $offset = null): array { return []; }
});
}
);
return $em;
}
// ─── setUp ─────────────────────────────────────────────────────────────────
protected function setUp(): void
{
$this->em = $this->createMock(EntityManagerInterface::class);
$this->logger = $this->createMock(LoggerInterface::class);
$this->service = new ActionService($this->em, $this->logger);
}
// ══════════════════════════════════════════════════════════════════════════
// suspendCustomer
// ══════════════════════════════════════════════════════════════════════════
public function testSuspendCustomerSuccess(): void
{
$customer = $this->makeCustomer(Customer::STATE_ACTIVE);
$customer->expects($this->once())->method('setState')->with(Customer::STATE_SUSPENDED);
$website = $this->makeWebsite(Website::STATE_OPEN);
$website->expects($this->once())->method('setState')->with(Website::STATE_SUSPENDED);
$user = $this->createMock(User::class);
$domain = new Domain($this->createStub(Customer::class), 'example.com');
$domainEmail = $this->makeDomainEmail('active');
$domainEmail->expects($this->once())->method('setState')->with('suspended');
$websiteRepo = $this->makeRepo([$website]);
$domainRepo = $this->makeRepo([$domain]);
$domainEmailRepo = $this->makeRepo([$domainEmail]);
$em = $this->makeEmWithRepos([
Website::class => $websiteRepo,
Domain::class => $domainRepo,
DomainEmail::class => $domainEmailRepo,
]);
$em->expects($this->atLeastOnce())->method('persist')->with($this->isInstanceOf(ActionLog::class));
$em->expects($this->atLeastOnce())->method('flush');
$service = new ActionService($em, $this->logger);
$result = $service->suspendCustomer($customer, 'Impaye');
$this->assertTrue($result);
}
public function testSuspendCustomerAlreadySuspended(): void
{
$customer = $this->makeCustomer(Customer::STATE_SUSPENDED);
$customer->expects($this->never())->method('setState');
$this->em->expects($this->once())->method('persist')->with($this->isInstanceOf(ActionLog::class));
$this->em->expects($this->once())->method('flush');
$result = $this->service->suspendCustomer($customer);
$this->assertTrue($result);
}
public function testSuspendCustomerException(): void
{
$customer = $this->makeCustomer(Customer::STATE_ACTIVE);
$customer->method('setState')->willThrowException(new \RuntimeException('DB error'));
// EM must be able to persist/flush the two ActionLogs (initial log + error log)
$this->em->expects($this->exactly(2))->method('persist')->with($this->isInstanceOf(ActionLog::class));
$this->em->expects($this->exactly(2))->method('flush');
$result = $this->service->suspendCustomer($customer);
$this->assertFalse($result);
}
public function testSuspendCustomerWithNoDomains(): void
{
$customer = $this->makeCustomer(Customer::STATE_ACTIVE);
$customer->expects($this->once())->method('setState')->with(Customer::STATE_SUSPENDED);
$websiteRepo = $this->makeRepo([]);
$domainRepo = $this->makeRepo([]);
$em = $this->makeEmWithRepos([
Website::class => $websiteRepo,
Domain::class => $domainRepo,
]);
$em->method('persist');
$em->method('flush');
$service = new ActionService($em, $this->logger);
$result = $service->suspendCustomer($customer, 'test');
$this->assertTrue($result);
}
// ══════════════════════════════════════════════════════════════════════════
// unsuspendCustomer
// ══════════════════════════════════════════════════════════════════════════
public function testUnsuspendCustomerSuccess(): void
{
$customer = $this->makeCustomer(Customer::STATE_SUSPENDED);
$customer->expects($this->once())->method('setState')->with(Customer::STATE_ACTIVE);
$website = $this->makeWebsite(Website::STATE_SUSPENDED);
$website->expects($this->once())->method('setState')->with(Website::STATE_OPEN);
$domain = new Domain($this->createStub(Customer::class), 'example.com');
$domainEmail = $this->makeDomainEmail('suspended');
$domainEmail->expects($this->once())->method('setState')->with('active');
$websiteRepo = $this->makeRepo([$website]);
$domainRepo = $this->makeRepo([$domain]);
$domainEmailRepo = $this->makeRepo([$domainEmail]);
$em = $this->makeEmWithRepos([
Website::class => $websiteRepo,
Domain::class => $domainRepo,
DomainEmail::class => $domainEmailRepo,
]);
$em->expects($this->atLeastOnce())->method('persist')->with($this->isInstanceOf(ActionLog::class));
$em->expects($this->atLeastOnce())->method('flush');
$service = new ActionService($em, $this->logger);
$result = $service->unsuspendCustomer($customer, 'Paiement recu');
$this->assertTrue($result);
}
public function testUnsuspendCustomerNotSuspended(): void
{
$customer = $this->makeCustomer(Customer::STATE_ACTIVE);
$customer->expects($this->never())->method('setState');
$this->em->expects($this->once())->method('persist')->with($this->isInstanceOf(ActionLog::class));
$this->em->expects($this->once())->method('flush');
$result = $this->service->unsuspendCustomer($customer);
$this->assertTrue($result);
}
public function testUnsuspendCustomerException(): void
{
$customer = $this->makeCustomer(Customer::STATE_SUSPENDED);
$customer->method('setState')->willThrowException(new \RuntimeException('DB error'));
// initial log + error log
$this->em->expects($this->exactly(2))->method('persist')->with($this->isInstanceOf(ActionLog::class));
$this->em->expects($this->exactly(2))->method('flush');
$result = $this->service->unsuspendCustomer($customer);
$this->assertFalse($result);
}
public function testUnsuspendCustomerWithNoSites(): void
{
$customer = $this->makeCustomer(Customer::STATE_SUSPENDED);
$customer->expects($this->once())->method('setState')->with(Customer::STATE_ACTIVE);
$websiteRepo = $this->makeRepo([]);
$domainRepo = $this->makeRepo([]);
$em = $this->makeEmWithRepos([
Website::class => $websiteRepo,
Domain::class => $domainRepo,
]);
$em->method('persist');
$em->method('flush');
$service = new ActionService($em, $this->logger);
$result = $service->unsuspendCustomer($customer);
$this->assertTrue($result);
}
// ══════════════════════════════════════════════════════════════════════════
// suspendWebsite
// ══════════════════════════════════════════════════════════════════════════
public function testSuspendWebsiteSuccess(): void
{
$customer = $this->makeCustomer();
$website = $this->makeWebsite(Website::STATE_OPEN);
$website->expects($this->once())->method('setState')->with(Website::STATE_SUSPENDED);
// flush() is called once in the public method + once inside log()
$this->em->expects($this->atLeastOnce())->method('flush');
$this->em->expects($this->once())->method('persist')->with($this->isInstanceOf(ActionLog::class));
$this->service->suspendWebsite($website, $customer, 'Impaye');
}
public function testSuspendWebsiteAlreadySuspended(): void
{
$customer = $this->makeCustomer();
$website = $this->makeWebsite(Website::STATE_SUSPENDED);
$website->expects($this->never())->method('setState');
$this->em->expects($this->never())->method('flush');
$this->em->expects($this->never())->method('persist');
$this->service->suspendWebsite($website, $customer);
}
// ══════════════════════════════════════════════════════════════════════════
// unsuspendWebsite
// ══════════════════════════════════════════════════════════════════════════
public function testUnsuspendWebsiteSuccess(): void
{
$customer = $this->makeCustomer();
$website = $this->makeWebsite(Website::STATE_SUSPENDED);
$website->expects($this->once())->method('setState')->with(Website::STATE_OPEN);
$this->em->expects($this->atLeastOnce())->method('flush');
$this->em->expects($this->once())->method('persist')->with($this->isInstanceOf(ActionLog::class));
$this->service->unsuspendWebsite($website, $customer, 'Paiement recu');
}
public function testUnsuspendWebsiteFromOpenState(): void
{
// unsuspendWebsite does NOT check current state — it always sets to OPEN
$customer = $this->makeCustomer();
$website = $this->makeWebsite(Website::STATE_OPEN);
$website->expects($this->once())->method('setState')->with(Website::STATE_OPEN);
$this->em->expects($this->atLeastOnce())->method('flush');
$this->em->expects($this->once())->method('persist')->with($this->isInstanceOf(ActionLog::class));
$this->service->unsuspendWebsite($website, $customer);
}
// ══════════════════════════════════════════════════════════════════════════
// suspendDomainEmail
// ══════════════════════════════════════════════════════════════════════════
public function testSuspendDomainEmailSuccess(): void
{
$customer = $this->makeCustomer();
$domainEmail = $this->makeDomainEmail('active');
$domainEmail->expects($this->once())->method('setState')->with('suspended');
$this->em->expects($this->atLeastOnce())->method('flush');
$this->em->expects($this->once())->method('persist')->with($this->isInstanceOf(ActionLog::class));
$this->service->suspendDomainEmail($domainEmail, $customer, 'Impaye');
}
public function testSuspendDomainEmailAlreadySuspended(): void
{
$customer = $this->makeCustomer();
$domainEmail = $this->makeDomainEmail('suspended');
$domainEmail->expects($this->never())->method('setState');
$this->em->expects($this->never())->method('flush');
$this->em->expects($this->never())->method('persist');
$this->service->suspendDomainEmail($domainEmail, $customer);
}
// ══════════════════════════════════════════════════════════════════════════
// unsuspendDomainEmail
// ══════════════════════════════════════════════════════════════════════════
public function testUnsuspendDomainEmailSuccess(): void
{
$customer = $this->makeCustomer();
$domainEmail = $this->makeDomainEmail('suspended');
$domainEmail->expects($this->once())->method('setState')->with('active');
$this->em->expects($this->atLeastOnce())->method('flush');
$this->em->expects($this->once())->method('persist')->with($this->isInstanceOf(ActionLog::class));
$this->service->unsuspendDomainEmail($domainEmail, $customer, 'Paiement recu');
}
public function testUnsuspendDomainEmailAlwaysSetsActive(): void
{
// Like unsuspendWebsite, this always sets state — no guard
$customer = $this->makeCustomer();
$domainEmail = $this->makeDomainEmail('active');
$domainEmail->expects($this->once())->method('setState')->with('active');
$this->em->expects($this->atLeastOnce())->method('flush');
$this->em->expects($this->once())->method('persist')->with($this->isInstanceOf(ActionLog::class));
$this->service->unsuspendDomainEmail($domainEmail, $customer);
}
// ══════════════════════════════════════════════════════════════════════════
// disableCustomer
// ══════════════════════════════════════════════════════════════════════════
public function testDisableCustomerSuccess(): void
{
$customer = $this->makeCustomer(Customer::STATE_SUSPENDED);
$customer->expects($this->once())->method('setState')->with(Customer::STATE_DISABLED);
// log() + flush inside log, then flush inside try block
$this->em->expects($this->once())->method('persist')->with($this->isInstanceOf(ActionLog::class));
$this->em->expects($this->atLeastOnce())->method('flush');
$result = $this->service->disableCustomer($customer, 'Resiliation');
$this->assertTrue($result);
}
public function testDisableCustomerException(): void
{
$customer = $this->makeCustomer(Customer::STATE_SUSPENDED);
$customer->method('setState')->willThrowException(new \RuntimeException('DB error'));
// initial log + error log
$this->em->expects($this->exactly(2))->method('persist')->with($this->isInstanceOf(ActionLog::class));
$this->em->expects($this->exactly(2))->method('flush');
$result = $this->service->disableCustomer($customer);
$this->assertFalse($result);
}
public function testDisableCustomerDefaultReason(): void
{
$customer = $this->makeCustomer(Customer::STATE_ACTIVE);
$customer->expects($this->once())->method('setState')->with(Customer::STATE_DISABLED);
$this->em->method('persist');
$this->em->method('flush');
$result = $this->service->disableCustomer($customer);
$this->assertTrue($result);
}
// ══════════════════════════════════════════════════════════════════════════
// markForDeletion
// ══════════════════════════════════════════════════════════════════════════
public function testMarkForDeletionSuccess(): void
{
$customer = $this->makeCustomer(Customer::STATE_DISABLED);
$customer->expects($this->once())->method('setState')->with(Customer::STATE_PENDING_DELETE);
$this->em->expects($this->once())->method('persist')->with($this->isInstanceOf(ActionLog::class));
$this->em->expects($this->atLeastOnce())->method('flush');
// The method also calls $this->logger->critical() directly (outside log())
$this->logger->expects($this->atLeastOnce())->method('critical');
$result = $this->service->markForDeletion($customer, 'Resiliation contrat');
$this->assertTrue($result);
}
public function testMarkForDeletionException(): void
{
$customer = $this->makeCustomer(Customer::STATE_DISABLED);
$customer->method('setState')->willThrowException(new \RuntimeException('DB error'));
// initial log + error log
$this->em->expects($this->exactly(2))->method('persist')->with($this->isInstanceOf(ActionLog::class));
$this->em->expects($this->exactly(2))->method('flush');
$result = $this->service->markForDeletion($customer);
$this->assertFalse($result);
}
public function testMarkForDeletionDefaultReason(): void
{
$customer = $this->makeCustomer(Customer::STATE_ACTIVE);
$customer->expects($this->once())->method('setState')->with(Customer::STATE_PENDING_DELETE);
$this->em->method('persist');
$this->em->method('flush');
$this->logger->method('critical');
$result = $this->service->markForDeletion($customer);
$this->assertTrue($result);
}
// ══════════════════════════════════════════════════════════════════════════
// log() private — severity branches (exercised via public methods)
// ══════════════════════════════════════════════════════════════════════════
/**
* suspendCustomer uses 'critical' severity → logger::critical()
* This also tests the 'warning' branch via the "already suspended" path.
*/
public function testLogSeverityCriticalBranch(): void
{
// The initial log in suspendCustomer for a non-suspended customer uses 'critical'
$customer = $this->makeCustomer(Customer::STATE_ACTIVE);
$customer->method('setState');
$this->em->method('persist');
$this->em->method('flush');
$this->em->method('getRepository')->willReturn($this->makeRepo([]));
$this->logger->expects($this->atLeastOnce())->method('critical');
$this->service->suspendCustomer($customer, 'Test critical log');
}
public function testLogSeverityWarningBranch(): void
{
// suspendCustomer with already-suspended customer triggers 'warning' log
$customer = $this->makeCustomer(Customer::STATE_SUSPENDED);
$this->em->method('persist');
$this->em->method('flush');
$this->logger->expects($this->once())->method('warning');
$this->service->suspendCustomer($customer);
}
public function testLogSeverityInfoBranch(): void
{
// unsuspendCustomer uses 'info' severity
$customer = $this->makeCustomer(Customer::STATE_SUSPENDED);
$customer->method('setState');
$this->em->method('persist');
$this->em->method('flush');
$this->em->method('getRepository')->willReturn($this->makeRepo([]));
$this->logger->expects($this->atLeastOnce())->method('info');
$this->service->unsuspendCustomer($customer);
}
public function testLogSeverityWarningBranchForUnsuspend(): void
{
// unsuspendCustomer with non-suspended customer triggers 'warning' log
$customer = $this->makeCustomer(Customer::STATE_ACTIVE);
$this->em->method('persist');
$this->em->method('flush');
$this->logger->expects($this->once())->method('warning');
$this->service->unsuspendCustomer($customer);
}
/**
* The private log() method has a 'danger' severity branch that maps to logger::error().
* We exercise it via reflection to ensure full method coverage.
*/
public function testLogSeverityDangerBranchCallsLoggerError(): void
{
$customer = $this->makeCustomer(Customer::STATE_ACTIVE);
$this->em->method('persist');
$this->em->method('flush');
// The 'danger' severity maps to $this->logger->error(...)
$this->logger->expects($this->once())->method('error');
$method = new \ReflectionMethod(ActionService::class, 'log');
$method->setAccessible(true);
$method->invoke(
$this->service,
ActionLog::ACTION_SUSPEND_CUSTOMER,
$customer,
'Test danger severity',
'danger',
true,
[],
);
}
// ══════════════════════════════════════════════════════════════════════════
// logError() private — exercised via exception paths above + dedicated test
// ══════════════════════════════════════════════════════════════════════════
public function testLogErrorPersistsActionLogWithErrorMessage(): void
{
$customer = $this->makeCustomer(Customer::STATE_ACTIVE);
$customer->method('setState')->willThrowException(new \InvalidArgumentException('Invalid state'));
$persistedLogs = [];
$this->em->method('persist')->willReturnCallback(
static function (object $obj) use (&$persistedLogs): void {
$persistedLogs[] = $obj;
}
);
$this->em->method('flush');
$this->service->disableCustomer($customer);
// There should be 2 ActionLog entries: the initial info log, then the error log
$this->assertCount(2, $persistedLogs);
/** @var ActionLog $errorLog */
$errorLog = $persistedLogs[1];
$this->assertInstanceOf(ActionLog::class, $errorLog);
$this->assertFalse($errorLog->isSuccess());
$this->assertNotNull($errorLog->getErrorMessage());
$this->assertStringContainsString('Invalid state', $errorLog->getErrorMessage());
}
// ══════════════════════════════════════════════════════════════════════════
// Edge cases — log() with entityId branch (via suspendWebsite/suspendDomainEmail)
// ══════════════════════════════════════════════════════════════════════════
public function testSuspendWebsiteSetsEntityIdInActionLog(): void
{
$customer = $this->makeCustomer();
$website = $this->makeWebsite(Website::STATE_OPEN);
$website->method('setState');
$persistedLogs = [];
$this->em->method('persist')->willReturnCallback(
static function (object $obj) use (&$persistedLogs): void {
$persistedLogs[] = $obj;
}
);
$this->em->method('flush');
$this->service->suspendWebsite($website, $customer);
$this->assertCount(1, $persistedLogs);
/** @var ActionLog $log */
$log = $persistedLogs[0];
$this->assertSame(ActionLog::ACTION_SUSPEND_WEBSITE, $log->getAction());
$this->assertSame(10, $log->getEntityId());
$this->assertSame('Website', $log->getEntityType());
}
public function testSuspendDomainEmailSetsEntityIdInActionLog(): void
{
$customer = $this->makeCustomer();
$domainEmail = $this->makeDomainEmail('active');
$domainEmail->method('setState');
$persistedLogs = [];
$this->em->method('persist')->willReturnCallback(
static function (object $obj) use (&$persistedLogs): void {
$persistedLogs[] = $obj;
}
);
$this->em->method('flush');
$this->service->suspendDomainEmail($domainEmail, $customer);
$this->assertCount(1, $persistedLogs);
/** @var ActionLog $log */
$log = $persistedLogs[0];
$this->assertSame(ActionLog::ACTION_SUSPEND_DOMAIN_EMAIL, $log->getAction());
$this->assertSame(20, $log->getEntityId());
$this->assertSame('DomainEmail', $log->getEntityType());
}
// ══════════════════════════════════════════════════════════════════════════
// suspendCustomer — multiple websites and domain emails
// ══════════════════════════════════════════════════════════════════════════
public function testSuspendCustomerSuspendsMultipleWebsitesAndEmails(): void
{
$customer = $this->makeCustomer(Customer::STATE_ACTIVE);
$customer->method('setState');
$website1 = $this->makeWebsite(Website::STATE_OPEN);
$website1->expects($this->once())->method('setState')->with(Website::STATE_SUSPENDED);
$website2 = $this->makeWebsite(Website::STATE_OPEN);
$website2->expects($this->once())->method('setState')->with(Website::STATE_SUSPENDED);
$domain = new Domain($this->createStub(Customer::class), 'example.com');
$domainEmail1 = $this->makeDomainEmail('active');
$domainEmail1->expects($this->once())->method('setState')->with('suspended');
$domainEmail2 = $this->makeDomainEmail('active');
$domainEmail2->expects($this->once())->method('setState')->with('suspended');
$websiteRepo = $this->makeRepo([$website1, $website2]);
$domainRepo = $this->makeRepo([$domain]);
$domainEmailRepo = $this->makeRepo([$domainEmail1, $domainEmail2]);
$em = $this->makeEmWithRepos([
Website::class => $websiteRepo,
Domain::class => $domainRepo,
DomainEmail::class => $domainEmailRepo,
]);
$em->method('persist');
$em->method('flush');
$service = new ActionService($em, $this->logger);
$result = $service->suspendCustomer($customer, 'Test multi');
$this->assertTrue($result);
}
// ══════════════════════════════════════════════════════════════════════════
// unsuspendCustomer — multiple websites and domain emails
// ══════════════════════════════════════════════════════════════════════════
public function testUnsuspendCustomerUnsuspendsMultipleWebsitesAndEmails(): void
{
$customer = $this->makeCustomer(Customer::STATE_SUSPENDED);
$customer->method('setState');
$website1 = $this->makeWebsite(Website::STATE_SUSPENDED);
$website1->expects($this->once())->method('setState')->with(Website::STATE_OPEN);
$website2 = $this->makeWebsite(Website::STATE_SUSPENDED);
$website2->expects($this->once())->method('setState')->with(Website::STATE_OPEN);
$domain = new Domain($this->createStub(Customer::class), 'example.com');
$domainEmail1 = $this->makeDomainEmail('suspended');
$domainEmail1->expects($this->once())->method('setState')->with('active');
$domainEmail2 = $this->makeDomainEmail('suspended');
$domainEmail2->expects($this->once())->method('setState')->with('active');
$websiteRepo = $this->makeRepo([$website1, $website2]);
$domainRepo = $this->makeRepo([$domain]);
$domainEmailRepo = $this->makeRepo([$domainEmail1, $domainEmail2]);
$em = $this->makeEmWithRepos([
Website::class => $websiteRepo,
Domain::class => $domainRepo,
DomainEmail::class => $domainEmailRepo,
]);
$em->method('persist');
$em->method('flush');
$service = new ActionService($em, $this->logger);
$result = $service->unsuspendCustomer($customer, 'Paiement recu');
$this->assertTrue($result);
}
}