Skip to content

Commit b54e2f1

Browse files
author
awu
committed
test: add unit tests for NdJson stream reading functionality
1 parent 0f64f0c commit b54e2f1

File tree

1 file changed

+143
-0
lines changed

1 file changed

+143
-0
lines changed

tests/Stream/NdJsonTest.php

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Thenativeweb\Eventsourcingdb\Tests\Stream;
6+
7+
use PHPUnit\Framework\TestCase;
8+
use Psr\Http\Message\StreamInterface;
9+
use RuntimeException;
10+
use Thenativeweb\Eventsourcingdb\Stream\NdJson;
11+
use Thenativeweb\Eventsourcingdb\Stream\ReadEventLine;
12+
13+
final class NdJsonTest extends TestCase
14+
{
15+
public function getEofReturnValues(string $jsonLines): array
16+
{
17+
$byteLine = $this->getReadReturnValues($jsonLines);
18+
19+
$eofReturnValues = array_fill(0, count($byteLine), false);
20+
$eofReturnValues[] = true;
21+
22+
return $eofReturnValues;
23+
}
24+
25+
public function getReadReturnValues(string $jsonLines): array
26+
{
27+
$eofFixChar = '-';
28+
$jsonLineCount = substr_count($jsonLines, "\n");
29+
return str_split($jsonLines . str_repeat($eofFixChar, $jsonLineCount));
30+
}
31+
32+
public function testReadLineReadsUntilNewline(): void
33+
{
34+
$stream = $this->createMock(StreamInterface::class);
35+
$stream->method('eof')
36+
->willReturnOnConsecutiveCalls(false, false, false, true);
37+
38+
$stream->method('read')
39+
->willReturnOnConsecutiveCalls('f', 'o', "\n");
40+
41+
$line = NdJson::readLine($stream);
42+
$this->assertSame("fo\n", $line);
43+
}
44+
45+
public function testReadLineReturnsEmptyStringIfNothingToRead(): void
46+
{
47+
$stream = $this->createMock(StreamInterface::class);
48+
$stream->method('eof')->willReturn(false);
49+
$stream->method('read')->willReturn('');
50+
51+
$line = NdJson::readLine($stream);
52+
$this->assertSame('', $line);
53+
}
54+
55+
public function testReadStreamYieldsEventLines(): void
56+
{
57+
$json1 = json_encode([
58+
'type' => 'event1',
59+
'payload' => [
60+
'foo' => 'bar',
61+
],
62+
]) . "\n";
63+
$json2 = json_encode([
64+
'type' => 'event2',
65+
'payload' => [
66+
'baz' => 'qux',
67+
],
68+
]) . "\n";
69+
$jsonLines = $json1 . $json2;
70+
71+
$stream = $this->createMock(StreamInterface::class);
72+
$stream->method('eof')
73+
->willReturnOnConsecutiveCalls(...$this->getEofReturnValues($jsonLines));
74+
$stream->method('read')
75+
->willReturnOnConsecutiveCalls(...$this->getReadReturnValues($jsonLines));
76+
77+
$events = iterator_to_array(NdJson::readStream($stream));
78+
79+
$this->assertCount(2, $events);
80+
$this->assertInstanceOf(ReadEventLine::class, $events[0]);
81+
$this->assertSame('event1', $events[0]->type);
82+
$this->assertSame([
83+
'foo' => 'bar',
84+
], $events[0]->payload);
85+
86+
$this->assertInstanceOf(ReadEventLine::class, $events[1]);
87+
$this->assertSame('event2', $events[1]->type);
88+
$this->assertSame([
89+
'baz' => 'qux',
90+
], $events[1]->payload);
91+
}
92+
93+
public function testReadStreamSkipsEmptyLines(): void
94+
{
95+
$jsonLines = json_encode([
96+
'type' => 'event',
97+
'payload' => [],
98+
]) . "\n";
99+
100+
$stream = $this->createMock(StreamInterface::class);
101+
$stream->method('eof')
102+
->willReturnOnConsecutiveCalls(...$this->getEofReturnValues($jsonLines));
103+
$stream->method('read')
104+
->willReturnOnConsecutiveCalls(...$this->getReadReturnValues($jsonLines));
105+
106+
$events = iterator_to_array(NdJson::readStream($stream));
107+
108+
$this->assertCount(1, $events);
109+
$this->assertSame('event', $events[0]->type);
110+
}
111+
112+
public function testReadStreamThrowsOnInvalidJson(): void
113+
{
114+
$this->expectException(RuntimeException::class);
115+
$this->expectExceptionMessage('Failed to read events.');
116+
117+
$jsonLines = "{ invalid json }\n";
118+
119+
$stream = $this->createMock(StreamInterface::class);
120+
$stream->method('eof')
121+
->willReturnOnConsecutiveCalls(...$this->getEofReturnValues($jsonLines));
122+
$stream->method('read')
123+
->willReturnOnConsecutiveCalls(...$this->getReadReturnValues($jsonLines));
124+
125+
iterator_to_array(NdJson::readStream($stream));
126+
}
127+
128+
public function testReadStreamThrowsIfDecodedJsonIsNotArray(): void
129+
{
130+
$this->expectException(RuntimeException::class);
131+
$this->expectExceptionMessage('Failed to read events, expected an array.');
132+
133+
$jsonLines = json_encode('just a string') . "\n";
134+
135+
$stream = $this->createMock(StreamInterface::class);
136+
$stream->method('eof')
137+
->willReturnOnConsecutiveCalls(...$this->getEofReturnValues($jsonLines));
138+
$stream->method('read')
139+
->willReturnOnConsecutiveCalls(...$this->getReadReturnValues($jsonLines));
140+
141+
iterator_to_array(NdJson::readStream($stream));
142+
}
143+
}

0 commit comments

Comments
 (0)