Skip to content

Commit 4086784

Browse files
authored
Merge pull request #16 from JMLamodiere/integration_infra_sociable
Use overlapping sociable tests
2 parents 8648fee + b029058 commit 4086784

16 files changed

+240
-135
lines changed

.travis.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ branches:
2929
- integration_infra_medium_domain
3030
- integration_infra_medium_domain_wiremock
3131
- integration_infra_medium_domain_no_di
32+
- integration_infra_sociable
3233

3334
before_install:
3435
- make preinstall

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,11 @@ decoupling HTTP tests with the library being used for HTTP calls.
3030
[(see Pull Request)](https://github.com/JMLamodiere/tdd-demo-forumphp2020/pull/15)
3131
removes [Dependency Injection Container](https://www.loosecouplings.com/2011/01/dependency-injection-using-di-container.html)
3232
usage and manually build tested classes instead.
33+
1. [integration_infra_sociable](https://github.com/JMLamodiere/tdd-demo-forumphp2020/tree/integration_infra_sociable) branch
34+
[(see Pull Request)](https://github.com/JMLamodiere/tdd-demo-forumphp2020/pull/16)
35+
replaces medium sized tests with [Overlapping Sociable Tests](https://www.jamesshore.com/v2/blog/2018/testing-without-mocks#sociable-tests)
36+
to allow easily test and evolve individual behaviours (ex : class serialization) while still being able to
37+
split/merge/refactor classes inside some class clusters by not checking specific calls between them.
3338
1. (todo...)
3439

3540
## API documentation

docs/openapi.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
openapi: 3.0.3
22
info:
33
title: TDD Demo ForumPHP 2020
4+
description: |
5+
See [JMLamodiere/tdd-demo-forumphp2020](https://github.com/JMLamodiere/tdd-demo-forumphp2020/blob/main/README.md) on GitHub.
46
57
version: 1.0.0
68

Lines changed: 12 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
<?php
22

33
use App\Infrastructure\Database\PostgresRunningSessionRepository;
4+
use App\Infrastructure\Database\PostgresRunningSessionRepositoryTest;
5+
use App\Infrastructure\Http\CurrentConditionDeserializerTest;
6+
use App\Infrastructure\Symfony\Serializer\RegisterRunningSessionDeserializerTest;
47
use Behat\Behat\Context\Context;
58
use Doctrine\DBAL\Connection;
69
use PHPUnit\Framework\Assert;
@@ -41,31 +44,7 @@ public function resetState()
4144
public function currentTemperatureIs($temperature)
4245
{
4346
$uri = '/currentconditions/v1/623?apikey='.$this->accuweatherApiKey;
44-
$body = <<<EOD
45-
[{
46-
"LocalObservationDateTime": "2020-10-17T17:50:00+02:00",
47-
"EpochTime": 1602949800,
48-
"WeatherText": "Mostly cloudy",
49-
"WeatherIcon": 6,
50-
"HasPrecipitation": false,
51-
"PrecipitationType": null,
52-
"IsDayTime": true,
53-
"Temperature": {
54-
"Metric": {
55-
"Value": $temperature,
56-
"Unit": "C",
57-
"UnitType": 17
58-
},
59-
"Imperial": {
60-
"Value": 55.0,
61-
"Unit": "F",
62-
"UnitType": 18
63-
}
64-
},
65-
"MobileLink": "http://m.accuweather.com/en/fr/paris/623/current-weather/623?lang=en-us",
66-
"Link": "http://www.accuweather.com/en/fr/paris/623/current-weather/623?lang=en-us"
67-
}]
68-
EOD;
47+
$body = CurrentConditionDeserializerTest::createBody($temperature);
6948

7049
$this->wireMock->stubFor(WireMock::get(WireMock::urlEqualTo($uri))
7150
->willReturn(WireMock::aResponse()
@@ -78,16 +57,10 @@ public function currentTemperatureIs($temperature)
7857
*/
7958
public function iRegisterARunningSessionWith($id, $distance, $shoes)
8059
{
81-
$request = Request::create('/runningsessions/'.$id, 'PUT', [], [], [], [], <<<EOD
82-
{
83-
"id": $id,
84-
"distance": $distance,
85-
"shoes": "$shoes"
86-
}
87-
EOD
88-
);
60+
$body = RegisterRunningSessionDeserializerTest::createBody($id, $distance, $shoes);
61+
$request = Request::create('/runningsessions/'.$id, 'PUT', [], [], [], [], $body);
8962

90-
$this->response = $this->kernel->handle($request); //, HttpKernelInterface::MASTER_REQUEST, false);
63+
$this->response = $this->kernel->handle($request);
9164
}
9265

9366
/**
@@ -96,15 +69,10 @@ public function iRegisterARunningSessionWith($id, $distance, $shoes)
9669
public function aRunningSessionShouldBeAddedWith($id, $distance, $shoes, $temperature)
9770
{
9871
Assert::assertEquals(201, $this->response->getStatusCode());
99-
100-
$row = $this->dbal->fetchAssociative(
101-
'SELECT distance, shoes, temperature_celcius '
102-
.' FROM '.PostgresRunningSessionRepository::TABLE_NAME
103-
.' WHERE ID = :id', [':id' => $id]);
104-
105-
Assert::assertIsArray($row, 'No session found with this id');
106-
Assert::assertEquals($distance, $row['distance']);
107-
Assert::assertEquals($shoes, $row['shoes']);
108-
Assert::assertEquals($temperature, $row['temperature_celcius']);
72+
PostgresRunningSessionRepositoryTest::thenRunningSessionTableShouldContain($this->dbal, $id, [
73+
'distance' => $distance,
74+
'shoes' => $shoes,
75+
'temperature_celcius' => $temperature,
76+
]);
10977
}
11078
}

src/Infrastructure/Http/CurrentConditionDeserializer.php

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,17 @@
44

55
namespace App\Infrastructure\Http;
66

7-
use Psr\Http\Message\ResponseInterface;
87
use Webmozart\Assert\Assert;
98

109
class CurrentConditionDeserializer
1110
{
12-
public function deserialize(ResponseInterface $response): float
11+
/**
12+
* @throws \InvalidArgumentException
13+
* @throws \JsonException
14+
*/
15+
public function deserialize(string $body): float
1316
{
14-
$content = $response->getBody()->getContents();
15-
$data = json_decode($content, true, 512, JSON_THROW_ON_ERROR);
17+
$data = json_decode($body, true, 512, JSON_THROW_ON_ERROR);
1618

1719
Assert::isArray($data, 'Data root should be array');
1820
Assert::notEmpty($data, 'Data root should not be empty');

src/Infrastructure/Http/RestWeatherProvider.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ public function getCurrentCelciusTemperature(): float
3939
}
4040

4141
try {
42-
return $this->serializer->deserialize($response);
42+
return $this->serializer->deserialize($response->getBody()->getContents());
4343
} catch (\Exception $previous) {
4444
throw new CannotGetCurrentTemperature('Cannot decode current condition', 0, $previous);
4545
}

src/Infrastructure/Symfony/Controller/RunningSessionController.php

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
use App\Application\Command\RegisterRunningSessionHandler;
88
use App\Infrastructure\Symfony\Serializer\RegisterRunningSessionDeserializer;
9-
use App\Infrastructure\Symfony\Serializer\RunningSessionNormalizer;
9+
use App\Infrastructure\Symfony\Serializer\RunningSessionSerializer;
1010
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
1111
use Symfony\Component\HttpFoundation\JsonResponse;
1212
use Symfony\Component\HttpFoundation\Request;
@@ -17,16 +17,16 @@
1717
class RunningSessionController extends AbstractController
1818
{
1919
private RegisterRunningSessionDeserializer $commandDeserializer;
20-
private RunningSessionNormalizer $responseNormalizer;
20+
private RunningSessionSerializer $responseSerializer;
2121
private RegisterRunningSessionHandler $registerRunningSessionHandler;
2222

2323
public function __construct(
2424
RegisterRunningSessionDeserializer $commandDeserializer,
25-
RunningSessionNormalizer $responseNormalizer,
25+
RunningSessionSerializer $responseSerializer,
2626
RegisterRunningSessionHandler $registerRunningSessionHandler
2727
) {
2828
$this->commandDeserializer = $commandDeserializer;
29-
$this->responseNormalizer = $responseNormalizer;
29+
$this->responseSerializer = $responseSerializer;
3030
$this->registerRunningSessionHandler = $registerRunningSessionHandler;
3131
}
3232

@@ -40,6 +40,12 @@ public function put(string $id, Request $request): Response
4040

4141
$session = $this->registerRunningSessionHandler->handle($command);
4242

43-
return new JsonResponse($this->responseNormalizer->normalize($session), Response::HTTP_CREATED);
43+
return new JsonResponse(
44+
$this->responseSerializer->serialize($session),
45+
Response::HTTP_CREATED,
46+
[],
47+
//json is already encoded by serializer
48+
true
49+
);
4450
}
4551
}

src/Infrastructure/Symfony/Serializer/RunningSessionNormalizer.php renamed to src/Infrastructure/Symfony/Serializer/RunningSessionSerializer.php

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,20 @@
66

77
use App\Domain\RunningSession;
88

9-
class RunningSessionNormalizer
9+
class RunningSessionSerializer
1010
{
11-
public function normalize(RunningSession $session): array
11+
/**
12+
* @throws \JsonException
13+
*/
14+
public function serialize(RunningSession $session): string
1215
{
13-
return [
16+
$data = [
1417
'id' => $session->getId(),
1518
'distance' => $session->getDistance(),
1619
'shoes' => $session->getShoes(),
1720
'temperatureCelcius' => $session->getMetricTemperature(),
1821
];
22+
23+
return json_encode($data, JSON_THROW_ON_ERROR);
1924
}
2025
}

tests/Application/Command/RegisterRunningSessionHandlerTest.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
namespace App\Application\Command;
66

77
use App\Domain\RunningSession;
8+
use App\Domain\RunningSessionFactory;
89
use App\Domain\RunningSessionRepository;
910
use App\Domain\WeatherProvider;
1011
use PHPUnit\Framework\TestCase;
@@ -45,7 +46,7 @@ public function testTheRunningSessionIRegisterIsEnrichedWithCurrentWeatherData()
4546
));
4647

4748
//Then (Assert)
48-
$this->thenARunningSessionShouldBeAdded(new RunningSession(
49+
$this->thenARunningSessionShouldBeAdded(RunningSessionFactory::create(
4950
12,
5051
125.7,
5152
'shoes',
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace App\Domain;
6+
7+
class RunningSessionFactory
8+
{
9+
public static function create(
10+
int $id = 9,
11+
float $distance = 999.1,
12+
string $shoes = 'shoes_value_not_used',
13+
float $metricTemperature = 98.76
14+
): RunningSession {
15+
return new RunningSession($id, $distance, $shoes, $metricTemperature);
16+
}
17+
}

0 commit comments

Comments
 (0)