Skip to content

Commit 4c98923

Browse files
committed
ISSUE-345: add tests
1 parent 1f46a30 commit 4c98923

File tree

4 files changed

+248
-0
lines changed

4 files changed

+248
-0
lines changed

tests/Helpers/DummyRequestDto.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace PhpList\RestBundle\Tests\Helpers;
6+
7+
use PhpList\RestBundle\Entity\RequestInterface;
8+
9+
class DummyRequestDto implements RequestInterface
10+
{
11+
12+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace PhpList\RestBundle\Tests\Integration\Service\Manager;
6+
7+
use PHPUnit\Framework\TestCase;
8+
use PhpList\RestBundle\Service\Manager\SubscriberManager;
9+
use PhpList\Core\Domain\Repository\Subscription\SubscriberRepository;
10+
use PhpList\RestBundle\Entity\SubscriberRequest;
11+
use PhpList\Core\Domain\Model\Subscription\Subscriber;
12+
13+
class SubscriberManagerTest extends TestCase
14+
{
15+
public function testCreateSubscriberPersistsAndReturnsProperlyInitializedEntity(): void
16+
{
17+
$repoMock = $this->createMock(SubscriberRepository::class);
18+
$repoMock
19+
->expects($this->once())
20+
->method('save')
21+
->with($this->callback(function (Subscriber $sub): bool {
22+
return $sub->getEmail() === '[email protected]'
23+
&& $sub->isConfirmed() === false
24+
&& $sub->isBlacklisted() === false
25+
&& $sub->hasHtmlEmail() === true
26+
&& $sub->isDisabled() === false;
27+
}));
28+
29+
$manager = new SubscriberManager($repoMock);
30+
31+
$dto = new SubscriberRequest();
32+
$dto->email = '[email protected]';
33+
$dto->requestConfirmation = true;
34+
$dto->htmlEmail = true;
35+
36+
$result = $manager->createSubscriber($dto);
37+
38+
$this->assertInstanceOf(Subscriber::class, $result);
39+
$this->assertSame('[email protected]', $result->getEmail());
40+
$this->assertFalse($result->isConfirmed());
41+
$this->assertFalse($result->isBlacklisted());
42+
$this->assertTrue($result->hasHtmlEmail());
43+
$this->assertFalse($result->isDisabled());
44+
}
45+
}
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace PhpList\RestBundle\Tests\Integration\Validator;
6+
7+
use PhpList\RestBundle\Entity\RequestInterface;
8+
use PhpList\RestBundle\Tests\Helpers\DummyRequestDto;
9+
use PhpList\RestBundle\Validator\RequestValidator;
10+
use PHPUnit\Framework\MockObject\MockObject;
11+
use PHPUnit\Framework\TestCase;
12+
use RuntimeException;
13+
use Symfony\Component\HttpFoundation\Request;
14+
use Symfony\Component\HttpKernel\Exception\UnprocessableEntityHttpException;
15+
use Symfony\Component\Serializer\SerializerInterface;
16+
use Symfony\Component\Validator\ConstraintViolation;
17+
use Symfony\Component\Validator\ConstraintViolationList;
18+
use Symfony\Component\Validator\Validator\ValidatorInterface;
19+
20+
class RequestValidatorTest extends TestCase
21+
{
22+
private SerializerInterface|MockObject $serializer;
23+
private ValidatorInterface|MockObject $validator;
24+
private RequestValidator $requestValidator;
25+
26+
protected function setUp(): void
27+
{
28+
$this->serializer = $this->createMock(SerializerInterface::class);
29+
$this->validator = $this->createMock(ValidatorInterface::class);
30+
$this->requestValidator = new RequestValidator(
31+
$this->serializer,
32+
$this->validator
33+
);
34+
}
35+
36+
public function testValidateReturnsDtoWhenJsonValidAndNoViolations(): void
37+
{
38+
$dto = $this->createMock(RequestInterface::class);
39+
$json = '{"foo":"bar"}';
40+
41+
$this->serializer
42+
->expects(self::once())
43+
->method('deserialize')
44+
->with($json, DummyRequestDto::class, 'json')
45+
->willReturn($dto);
46+
47+
$this->validator
48+
->expects(self::once())
49+
->method('validate')
50+
->with($dto)
51+
->willReturn(new ConstraintViolationList());
52+
53+
$request = new Request([], [], [], [], [], [], $json);
54+
55+
$result = $this->requestValidator->validate($request, DummyRequestDto::class);
56+
self::assertSame($dto, $result);
57+
}
58+
59+
public function testValidateThrowsOnInvalidJson(): void
60+
{
61+
$json = '{ invalid json }';
62+
$request = new Request([], [], [], [], [], [], $json);
63+
64+
$this->serializer
65+
->expects(self::once())
66+
->method('deserialize')
67+
->willThrowException(new RuntimeException('Syntax error'));
68+
69+
$this->expectException(UnprocessableEntityHttpException::class);
70+
$this->expectExceptionMessage('Invalid JSON: Syntax error');
71+
72+
$this->requestValidator->validate($request, DummyRequestDto::class);
73+
}
74+
75+
public function testValidateThrowsOnConstraintViolations(): void
76+
{
77+
$dto = $this->createMock(RequestInterface::class);
78+
$json = '{"email":"bad"}';
79+
$request = new Request([], [], [], [], [], [], $json);
80+
81+
$this->serializer
82+
->method('deserialize')
83+
->willReturn($dto);
84+
85+
$violation1 = new ConstraintViolation(
86+
'Must not be blank',
87+
'',
88+
[],
89+
null,
90+
'email',
91+
''
92+
);
93+
$violation2 = new ConstraintViolation(
94+
'Must be a valid email',
95+
'',
96+
[],
97+
null,
98+
'email',
99+
'bad'
100+
);
101+
$violations = new ConstraintViolationList([$violation1, $violation2]);
102+
103+
$this->validator
104+
->method('validate')
105+
->with($dto)
106+
->willReturn($violations);
107+
108+
$this->expectException(UnprocessableEntityHttpException::class);
109+
110+
$this->expectExceptionMessage("email: Must not be blank\nemail: Must be a valid email");
111+
112+
$this->requestValidator->validate($request, DummyRequestDto::class);
113+
}
114+
}
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace PhpList\RestBundle\Tests\Integration\Validator;
6+
7+
use PhpList\Core\Domain\Repository\Subscription\SubscriberRepository;
8+
use PhpList\RestBundle\Validator\UniqueEmail;
9+
use PhpList\RestBundle\Validator\UniqueEmailValidator;
10+
use PHPUnit\Framework\MockObject\MockObject;
11+
use PHPUnit\Framework\TestCase;
12+
use Symfony\Component\HttpKernel\Exception\ConflictHttpException;
13+
use Symfony\Component\Validator\Constraint;
14+
use Symfony\Component\Validator\Exception\UnexpectedTypeException;
15+
use Symfony\Component\Validator\Exception\UnexpectedValueException;
16+
17+
class UniqueEmailValidatorTest extends TestCase
18+
{
19+
private SubscriberRepository|MockObject $repo;
20+
private UniqueEmailValidator $validator;
21+
22+
protected function setUp(): void
23+
{
24+
$this->repo = $this->createMock(SubscriberRepository::class);
25+
$this->validator = new UniqueEmailValidator($this->repo);
26+
}
27+
28+
public function testThrowsUnexpectedTypeExceptionWhenConstraintIsWrong(): void
29+
{
30+
$this->expectException(UnexpectedTypeException::class);
31+
$this->validator->validate('anything', $this->createMock(Constraint::class));
32+
}
33+
34+
public function testSkipsValidationForNullOrEmpty(): void
35+
{
36+
$this->repo->expects(self::never())->method('findOneBy');
37+
38+
$this->validator->validate(null, new UniqueEmail());
39+
$this->validator->validate('', new UniqueEmail());
40+
41+
$this->addToAssertionCount(1);
42+
}
43+
44+
public function testThrowsUnexpectedValueExceptionForNonString(): void
45+
{
46+
$this->expectException(UnexpectedValueException::class);
47+
$this->validator->validate(123, new UniqueEmail());
48+
}
49+
50+
public function testThrowsConflictHttpExceptionWhenEmailAlreadyExists(): void
51+
{
52+
$email = '[email protected]';
53+
54+
$this->repo
55+
->expects(self::once())
56+
->method('findOneBy')
57+
->with(['email' => $email])
58+
->willReturn((object)['email' => $email]);
59+
60+
$this->expectException(ConflictHttpException::class);
61+
$this->expectExceptionMessage('Email already exists.');
62+
63+
$this->validator->validate($email, new UniqueEmail());
64+
}
65+
66+
public function testAllowsUniqueEmailWhenNoExistingSubscriber(): void
67+
{
68+
$this->repo
69+
->expects(self::once())
70+
->method('findOneBy')
71+
->willReturn(null);
72+
73+
$this->validator->validate('[email protected]', new UniqueEmail());
74+
75+
$this->addToAssertionCount(1);
76+
}
77+
}

0 commit comments

Comments
 (0)