Skip to content

Commit 2156267

Browse files
committed
Integration tests for Infrastructure, medium unit tests for Domain
1 parent 7bc90cd commit 2156267

13 files changed

+209
-347
lines changed

.travis.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,12 @@ jobs:
2121
fast_finish: true
2222

2323
branches:
24+
# Those branch will not be deleted. We want push to them without a Pull Request, but trigger the CI anyway
2425
only:
2526
- main
2627
- bad_implementation
2728
- bad_tests
29+
- integration_infra_medium_domain
2830

2931
before_install:
3032
- make preinstall

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@ contains :
1616
1. [bad_tests](https://github.com/JMLamodiere/tdd-demo-forumphp2020/tree/bad_tests) branch
1717
[(see Pull Request)](https://github.com/JMLamodiere/tdd-demo-forumphp2020/pull/12) only fixes (some) hexagonal mistakes.
1818
Many obscure changes are required in the tests, proving they do not help much during refactoring
19+
1. [integration_infra_medium_domain](https://github.com/JMLamodiere/tdd-demo-forumphp2020/tree/integration_infra_medium_domain) branch
20+
[(see Pull Request)](https://github.com/JMLamodiere/tdd-demo-forumphp2020/pull/13) split tests this way:
21+
- Domain logic (Application/Domain folders): medium Unit tests, mocking only infrastructure
22+
- Technical logic (Infrastructure folder): integration tests for each specific technology
1923
1. (todo...)
2024

2125
## API documentation

config/services.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,11 @@ services:
2727

2828
# add more service definitions when explicit configuration is needed
2929
# please note that last definitions always *replace* previous ones
30+
31+
# Mark Command/Query handlers public to allow mocking them in controller tests
32+
App\Application\Command\RegisterRunningSessionHandler:
33+
public: true
34+
3035
guzzle.accuweather:
3136
class: GuzzleHttp\Client
3237
arguments:

docs/openapi.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,8 @@ components:
6060
required: [ temperatureCelcius ]
6161
properties:
6262
temperatureCelcius:
63-
type: integer
63+
type: float
64+
example: 37.2
6465

6566
RunningSessionId:
6667
type: integer

tests/Application/Command/RegisterRunningSessionHandlerTest.php

Lines changed: 34 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
use App\Domain\RunningSessionRepository;
99
use App\Domain\WeatherProvider;
1010
use PHPUnit\Framework\TestCase;
11-
use Prophecy\Argument;
1211
use Prophecy\PhpUnit\ProphecyTrait;
1312
use Prophecy\Prophecy\ObjectProphecy;
1413

@@ -33,28 +32,43 @@ protected function setUp(): void
3332
);
3433
}
3534

36-
public function testHandle()
35+
public function testTheRunningSessionIRegisterIsEnrichedWithCurrentWeatherData()
3736
{
38-
$temperature = 15.5;
39-
/** @var ObjectProphecy|RegisterRunningSession $command */
40-
$command = $this->prophesize(RegisterRunningSession::class);
41-
$command->getId()
42-
->shouldBeCalledTimes(1)
43-
->willReturn(12);
44-
$command->getDistance()
45-
->shouldBeCalledTimes(1)
46-
->willReturn(25.7);
47-
$command->getShoes()
48-
->shouldBeCalledTimes(1)
49-
->willReturn('shoes');
50-
51-
$this->weatherProvider->getCurrentCelciusTemperature()
52-
->shouldBeCalledTimes(1)
37+
//Given (Arrange)
38+
$this->givenCrrentTemperatureIs(15.5);
39+
40+
//When (Act)
41+
$this->whenIRegisterARunningSession(new RegisterRunningSession(
42+
12,
43+
125.7,
44+
'shoes'
45+
));
46+
47+
//Then (Assert)
48+
$this->thenARunningSessionShouldBeAdded(new RunningSession(
49+
12,
50+
125.7,
51+
'shoes',
52+
15.5
53+
));
54+
}
55+
56+
private function givenCrrentTemperatureIs(float $temperature): void
57+
{
58+
$this->weatherProvider
59+
->getCurrentCelciusTemperature()
5360
->willReturn($temperature);
61+
}
5462

55-
$this->repository->add(Argument::type(RunningSession::class))
56-
->shouldBeCalledTimes(1);
63+
private function whenIRegisterARunningSession(RegisterRunningSession $command): void
64+
{
65+
$this->handler->handle($command);
66+
}
5767

58-
$this->handler->handle($command->reveal());
68+
private function thenARunningSessionShouldBeAdded(RunningSession $expectedAddedEntity)
69+
{
70+
$this->repository
71+
->add($expectedAddedEntity)
72+
->shouldHaveBeenCalled();
5973
}
6074
}

tests/Application/Command/RegisterRunningSessionTest.php

Lines changed: 0 additions & 23 deletions
This file was deleted.

tests/Domain/RunningSessionTest.php

Lines changed: 0 additions & 25 deletions
This file was deleted.

tests/Infrastructure/Database/PostgresRunningSessionRepositoryTest.php

Lines changed: 38 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -6,75 +6,56 @@
66

77
use App\Domain\RunningSession;
88
use Doctrine\DBAL\Connection;
9-
use Doctrine\DBAL\Query\QueryBuilder;
10-
use PHPUnit\Framework\TestCase;
11-
use Prophecy\Argument;
12-
use Prophecy\PhpUnit\ProphecyTrait;
13-
use Prophecy\Prophecy\ObjectProphecy;
9+
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
1410

15-
class PostgresRunningSessionRepositoryTest extends TestCase
11+
/**
12+
* @group integration
13+
*/
14+
class PostgresRunningSessionRepositoryTest extends KernelTestCase
1615
{
17-
use ProphecyTrait;
18-
19-
/** @var ObjectProphecy|Connection */
20-
private $dbal;
21-
16+
private Connection $dbal;
2217
private PostgresRunningSessionRepository $repository;
2318

2419
protected function setUp(): void
2520
{
26-
$this->dbal = $this->prophesize(Connection::class);
27-
$this->repository = new PostgresRunningSessionRepository($this->dbal->reveal());
21+
self::bootKernel();
22+
$this->dbal = self::$container->get('doctrine.dbal.default_connection');
23+
$this->repository = self::$container->get(PostgresRunningSessionRepository::class);
24+
$this->resetState();
2825
}
2926

30-
public function testAdd()
27+
private function resetState(): void
3128
{
32-
/** @var ObjectProphecy|QueryBuilder $queryBuilder */
33-
$queryBuilder = $this->prophesize(QueryBuilder::class);
34-
35-
/** @var ObjectProphecy|RunningSession $session */
36-
$session = $this->prophesize(RunningSession::class);
37-
$session->getId()
38-
->shouldBeCalledTimes(1)
39-
->willReturn($id = 12);
40-
$session->getDistance()
41-
->shouldBeCalledTimes(1)
42-
->willReturn($distance = 25.7);
43-
$session->getShoes()
44-
->shouldBeCalledTimes(1)
45-
->willReturn($shoes = 'shoes');
46-
$session->getMetricTemperature()
47-
->shouldBeCalledTimes(1)
48-
->willReturn($temperature = 25.3);
49-
50-
$this->dbal->createQueryBuilder()
51-
->shouldBeCalledTimes(1)
52-
->willReturn($queryBuilder);
29+
$this->dbal->executeStatement('TRUNCATE TABLE '.PostgresRunningSessionRepository::TABLE_NAME);
30+
}
5331

54-
$queryBuilder->insert(PostgresRunningSessionRepository::TABLE_NAME)
55-
->shouldBeCalledTimes(1)
56-
->willReturn($queryBuilder);
32+
public function testRunningSessionIsInserted()
33+
{
34+
//When (Act)
35+
$session = new RunningSession(55, 122.3, 'The shoes!', 34.5);
36+
$this->repository->add($session);
37+
38+
//Then (Assert)
39+
$this->thenRunningSessionTableShouldContain(55, [
40+
//DB result will be strings
41+
'distance' => '122.3',
42+
'shoes' => 'The shoes!',
43+
'temperature_celcius' => '34.5',
44+
]);
45+
}
5746

58-
$queryBuilder->setValue(Argument::cetera())
59-
->shouldBeCalledTimes(4)
60-
->willReturn($queryBuilder);
47+
private function thenRunningSessionTableShouldContain(int $id, array $expectedArray)
48+
{
49+
$row = $this->dbal->fetchAssociative(
50+
'SELECT distance, shoes, temperature_celcius '
51+
.' FROM RUNNING_SESSION'
52+
.' WHERE ID = :id', [':id' => $id]);
6153

62-
$queryBuilder->setParameter(':id', $id)
63-
->shouldBeCalledTimes(1)
64-
->willReturn($queryBuilder);
65-
$queryBuilder->setParameter(':distance', $distance)
66-
->shouldBeCalledTimes(1)
67-
->willReturn($queryBuilder);
68-
$queryBuilder->setParameter(':shoes', $shoes)
69-
->shouldBeCalledTimes(1)
70-
->willReturn($queryBuilder);
71-
$queryBuilder->setParameter(':celcius', $temperature)
72-
->shouldBeCalledTimes(1)
73-
->willReturn($queryBuilder);
74-
$queryBuilder->execute()
75-
->shouldBeCalledTimes(1)
76-
->willReturn(1);
54+
self::assertIsArray($row, 'No session found with this id');
7755

78-
$this->repository->add($session->reveal());
56+
//Avoid failing if key order is different
57+
asort($row);
58+
asort($expectedArray);
59+
self::assertSame($expectedArray, $row);
7960
}
8061
}

tests/Infrastructure/Http/CurrentConditionDeserializerTest.php

Lines changed: 0 additions & 45 deletions
This file was deleted.

0 commit comments

Comments
 (0)