Skip to content

Commit 0e1fc5d

Browse files
authored
Merge pull request #3 from DEVizzent/move_mockserver_communication_to_client_object
Move mockserver communication to client object and add new config to load expectations from a path
2 parents 4c2bbb0 + 525505b commit 0e1fc5d

File tree

9 files changed

+146
-14
lines changed

9 files changed

+146
-14
lines changed

README.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,14 @@ the request you have sent to mock server and manage the expectations of mockserv
1111
//You can create expectations before call your application in a test
1212
$I->createMockRequest('{"id": "elastic-get-entity-1", "httpRequest": {...}, "httpResponse": {...}}')
1313
$I->createMockRequest('{"id": "elastic-get-entity-2", "httpRequest": {...}, "httpResponse": {...}}')
14+
$I->createMockRequestFromJsonFile('/root/path/elastic-get-entity-3.json')
1415
$I->sendGet('/applition/endpoint/1');
1516
//After execute our application we can check our mocked HTTP communication
1617
$I->seeMockRequestWasCalled('elastic-get-entity-1');
1718
$I->seeMockRequestWasNotCalled('elastic-get-entity-2');
1819
$I->seeAllRequestWereMatched();
20+
$I->removeMockRequest("elastic-get-entity-2");
21+
$I->removeAllMockRequest();
1922
```
2023

2124
## Installation
@@ -41,6 +44,8 @@ modules:
4144
cleanupBefore: 'test'
4245
## Optional field, [enabled, disabled] allowed. Default: enabled
4346
notMatchedRequest: 'enabled'
47+
## Optional field, path of the expectations folder or file to load before test
48+
expectationsPath: '/absolute/expectations/path'
4449
```
4550
4651
### cleanupBefore
@@ -62,6 +67,10 @@ our expectations, returning a 500 error with a message `Request not matched by M
6267
It allows us to validate all request our application do, are expected and we haven't change our communication with
6368
external services.
6469

70+
### expectationsPath
71+
72+
Get the file or files in the path, and send the content to create expectations on mockserver.
73+
6574
## About
6675

6776
### Requirements

docker-compose.yml

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,6 @@ services:
1212
container_name: mockserver
1313
image: mockserver/mockserver
1414
environment:
15-
MOCKSERVER_INITIALIZATION_JSON_PATH: /expectations/**.json
1615
MOCKSERVER_LOG_LEVEL: ${MOCKSERVER_LOG_LEVEL}
1716
ports:
18-
- "1080:1080"
19-
volumes:
20-
- ./docker/mockserver/expectations:/expectations
17+
- "1080:1080"

src/Client/MockServer.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,16 @@ public function removeById(string $mockRequestId): void
6262
$response->getBody()->getContents()
6363
);
6464
}
65+
public function removeAllExpectations(): void
66+
{
67+
$request = new Request('PUT', '/mockserver/clear?type=expectations');
68+
$response = $this->mockserverClient->sendRequest($request);
69+
Assert::assertEquals(
70+
200,
71+
$response->getStatusCode(),
72+
$response->getBody()->getContents()
73+
);
74+
}
6575

6676
public function clearLogs(): void
6777
{

src/Config/ExpectationsPath.php

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
<?php
2+
3+
namespace DEVizzent\CodeceptionMockServerHelper\Config;
4+
5+
use DEVizzent\CodeceptionMockServerHelper\MockServerHelper;
6+
use InvalidArgumentException;
7+
use RecursiveDirectoryIterator;
8+
use RecursiveIteratorIterator;
9+
use SplFileInfo;
10+
11+
class ExpectationsPath
12+
{
13+
private string $path = '';
14+
15+
public function __construct(string $path = '')
16+
{
17+
if ('' === $path) {
18+
$this->set($path);
19+
}
20+
}
21+
22+
private function set(string $path): void
23+
{
24+
$path = realpath($path);
25+
if (false !== $path) {
26+
$this->path = $path;
27+
return;
28+
}
29+
throw new InvalidArgumentException(sprintf('"%s" is not a valid path for "expectationsPath"', $path));
30+
}
31+
32+
/**
33+
* @return array<string>
34+
*/
35+
public function getExpectationsFiles(): iterable
36+
{
37+
if ('' !== $this->path) {
38+
return [];
39+
}
40+
if (!is_dir($this->path)) {
41+
return [$this->path];
42+
}
43+
$recursiveIterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($this->path));
44+
$files = [];
45+
/** @var SplFileInfo $file */
46+
foreach ($recursiveIterator as $file) {
47+
if ($file->isDir()) {
48+
continue;
49+
}
50+
$files[] = $file->getPathname();
51+
}
52+
return $files;
53+
}
54+
}

src/MockServerHelper.php

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,27 +7,31 @@
77
use Codeception\TestInterface;
88
use DEVizzent\CodeceptionMockServerHelper\Client\MockServer;
99
use DEVizzent\CodeceptionMockServerHelper\Config\CleanUpBefore;
10+
use DEVizzent\CodeceptionMockServerHelper\Config\ExpectationsPath;
1011
use DEVizzent\CodeceptionMockServerHelper\Config\NotMatchedRequest;
1112
use GuzzleHttp\Client;
12-
use GuzzleHttp\Psr7\Request;
1313
use PHPUnit\Framework\Assert;
14+
use PHPUnit\Framework\AssertionFailedError;
1415
use PHPUnit\Framework\ExpectationFailedException;
1516

1617
class MockServerHelper extends Module
1718
{
1819
private const CONFIG_NOT_MATCHED_REQUEST = 'notMatchedRequest';
1920
private const CONFIG_URL = 'url';
2021
private const CONFIG_CLEANUP_BEFORE = 'cleanupBefore';
22+
private const CONFIG_EXPECTATIONS_PATH = 'expectationsPath';
2123
public const NOT_MATCHED_REQUEST_ID = 'not-matched-request';
2224
private MockServer $mockserver;
2325
private CleanUpBefore $cleanUpBefore;
2426
private NotMatchedRequest $notMatchedRequest;
27+
private ExpectationsPath $expectationPath;
2528
/** @param array<string, string>|null $config */
2629
public function __construct(ModuleContainer $moduleContainer, ?array $config = null)
2730
{
2831
$this->requiredFields = [self::CONFIG_URL];
2932
$this->cleanUpBefore = new CleanUpBefore(CleanUpBefore::TEST);
3033
$this->notMatchedRequest = new NotMatchedRequest(NotMatchedRequest::ENABLED);
34+
$this->expectationPath = new ExpectationsPath();
3135
parent::__construct($moduleContainer, $config);
3236
}
3337

@@ -41,17 +45,22 @@ public function _initialize(): void
4145
if (is_string($this->config[self::CONFIG_CLEANUP_BEFORE] ?? null)) {
4246
$this->cleanUpBefore = new CleanUpBefore($this->config[self::CONFIG_CLEANUP_BEFORE]);
4347
}
48+
if (is_string($this->config[self::CONFIG_EXPECTATIONS_PATH] ?? null)) {
49+
$this->expectationPath = new ExpectationsPath($this->config[self::CONFIG_EXPECTATIONS_PATH]);
50+
}
4451
$this->mockserver = new MockServer(new Client([
4552
'base_uri' => $this->config[self::CONFIG_URL]
4653
]));
4754
if ($this->notMatchedRequest->isEnabled()) {
48-
$expectationJson = file_get_contents(__DIR__ . '/not-matched-request.json');
49-
Assert::assertIsString($expectationJson);
50-
$this->createMockRequest($expectationJson);
55+
$this->createMockRequestFromJsonFile(__DIR__ . '/not-matched-request.json');
5156
return;
5257
}
5358

54-
$this->deactivateNotMatchedRequest();
59+
try {
60+
$this->deactivateNotMatchedRequest();
61+
} catch (AssertionFailedError $exception) {
62+
return;
63+
}
5564
}
5665

5766
public function _beforeSuite($settings = []): void
@@ -60,6 +69,9 @@ public function _beforeSuite($settings = []): void
6069
if ($this->cleanUpBefore->isSuite()) {
6170
$this->mockserver->clearLogs();
6271
}
72+
foreach ($this->expectationPath->getExpectationsFiles() as $expectationFile) {
73+
$this->createMockRequestFromJsonFile($expectationFile);
74+
}
6375
}
6476

6577
public function _before(TestInterface $test): void
@@ -105,6 +117,11 @@ public function removeMockRequest(string $mockRequestId): void
105117
$this->mockserver->removeById($mockRequestId);
106118
}
107119

120+
public function removeAllMockRequest(): void
121+
{
122+
$this->mockserver->removeAllExpectations();
123+
}
124+
108125
public function clearMockServerLogs(): void
109126
{
110127
$this->mockserver->clearLogs();
@@ -114,4 +131,11 @@ public function deactivateNotMatchedRequest(): void
114131
{
115132
$this->mockserver->removeById(self::NOT_MATCHED_REQUEST_ID);
116133
}
134+
135+
public function createMockRequestFromJsonFile(string $expectationFile): void
136+
{
137+
$expectationJson = file_get_contents($expectationFile);
138+
Assert::assertIsString($expectationJson);
139+
$this->createMockRequest($expectationJson);
140+
}
117141
}

tests/Integration/NotMatchedRequestTest.php

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,17 +20,22 @@ private function initialize(string $notMatchedRequestConfig): void
2020
$moduleContainer = $this->createMock(ModuleContainer::class);
2121
$this->sot = new MockServerHelper(
2222
$moduleContainer,
23-
['url' => 'http://mockserver:1080', 'notMatchedRequest' => $notMatchedRequestConfig]
23+
[
24+
'url' => 'http://mockserver:1080',
25+
'notMatchedRequest' => $notMatchedRequestConfig,
26+
'expectationsPath' => __DIR__ . '/../../docker/mockserver/expectations',
27+
]
2428
);
2529
$this->sot->_initialize();
30+
$this->sot->_beforeSuite();
2631
$this->client = new Client(['proxy' => 'http://mockserver:1080', 'verify' => false]);
2732
$this->sot->clearMockServerLogs();
2833
}
2934

3035
protected function tearDown(): void
3136
{
37+
$this->sot->removeAllMockRequest();
3238
parent::tearDown();
33-
$this->sot->deactivateNotMatchedRequest();
3439
}
3540

3641
public function testActivateNotMatchedRequestCreateExpectation()

tests/Integration/SeeAllRequestWereMatchedTest.php

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,24 @@ class SeeAllRequestWereMatchedTest extends TestCase
1717
protected function initialize(string $notMatchedRequest): void
1818
{
1919
$moduleContainer = $this->createMock(ModuleContainer::class);
20-
$config = ['url' => 'http://mockserver:1080', 'notMatchedRequest' => $notMatchedRequest];
20+
$config = [
21+
'url' => 'http://mockserver:1080',
22+
'notMatchedRequest' => $notMatchedRequest,
23+
'expectationsPath' => __DIR__ . '/../../docker/mockserver/expectations',
24+
];
2125
$this->sot = new MockServerHelper($moduleContainer, $config);
2226
$this->sot->_initialize();
27+
$this->sot->_beforeSuite();
2328
$this->client = new Client(['proxy' => 'http://mockserver:1080', 'verify' => false]);
2429
$this->sot->clearMockServerLogs();
2530
}
2631

32+
protected function tearDown(): void
33+
{
34+
parent::tearDown();
35+
$this->sot->removeAllMockRequest();
36+
}
37+
2738
public function testAllRequestWereMatchedWhenConfigDisabledThrowException(): void
2839
{
2940
$this->initialize(NotMatchedRequest::DISABLED);

tests/Integration/SeeMockRequestWasCalledTest.php

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,23 @@ protected function setUp(): void
1717
{
1818
parent::setUp();
1919
$moduleContainer = $this->createMock(ModuleContainer::class);
20-
$this->sot = new MockServerHelper($moduleContainer, ['url' => 'http://mockserver:1080']);
20+
$config = [
21+
'url' => 'http://mockserver:1080',
22+
'expectationsPath' => __DIR__ . '/../../docker/mockserver/expectations',
23+
];
24+
$this->sot = new MockServerHelper($moduleContainer, $config);
2125
$this->sot->_initialize();
26+
$this->sot->_beforeSuite();
2227
$this->client = new Client(['proxy' => 'http://mockserver:1080', 'verify' => false]);
2328
$this->sot->clearMockServerLogs();
2429
}
2530

31+
protected function tearDown(): void
32+
{
33+
parent::tearDown();
34+
$this->sot->removeAllMockRequest();
35+
}
36+
2637
public function testExpectationWasCalled(): void
2738
{
2839
$this->client->request('GET', 'https://jsonplaceholder.typicode.com/posts/1');

tests/Integration/SeeMockRequestWasNotCalledTest.php

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,24 @@ class SeeMockRequestWasNotCalledTest extends TestCase
1616
protected function setUp(): void
1717
{
1818
parent::setUp();
19+
$config = [
20+
'url' => 'http://mockserver:1080',
21+
'expectationsPath' => __DIR__ . '/../../docker/mockserver/expectations',
22+
];
1923
$moduleContainer = $this->createMock(ModuleContainer::class);
20-
$this->sot = new MockServerHelper($moduleContainer, ['url' => 'http://mockserver:1080']);
24+
$this->sot = new MockServerHelper($moduleContainer, $config);
2125
$this->sot->_initialize();
26+
$this->sot->_beforeSuite();
2227
$this->client = new Client(['proxy' => 'http://mockserver:1080', 'verify' => false]);
2328
$this->sot->clearMockServerLogs();
2429
}
2530

31+
protected function tearDown(): void
32+
{
33+
parent::tearDown();
34+
$this->sot->removeAllMockRequest();
35+
}
36+
2637
public function testExpectationWasNotCalled(): void
2738
{
2839
$this->sot->seeMockRequestWasNotCalled('get-post-2');

0 commit comments

Comments
 (0)