Skip to content

Commit 930fb18

Browse files
committed
Ignore extra fields in change stream document comparisons
MongoDB 4.0 adds a "clusterTime" field to change stream documents. Rather than add conditional logic to expect this in tests, implement a new comparison function that fields not found in our expected document.
1 parent c0d3551 commit 930fb18

File tree

3 files changed

+52
-17
lines changed

3 files changed

+52
-17
lines changed

tests/DocumentationExamplesTest.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -979,7 +979,7 @@ public function testChangeStreamExample_1_4()
979979
'documentKey' => ['_id' => 1],
980980
];
981981

982-
$this->assertSameDocument($expectedChange, $lastChange);
982+
$this->assertMatchesDocument($expectedChange, $lastChange);
983983

984984
// Start Changestream Example 3
985985
$resumeToken = ($lastChange !== null) ? $lastChange->_id : null;
@@ -1002,7 +1002,7 @@ public function testChangeStreamExample_1_4()
10021002
'documentKey' => ['_id' => 2],
10031003
];
10041004

1005-
$this->assertSameDocument($expectedChange, $nextChange);
1005+
$this->assertMatchesDocument($expectedChange, $nextChange);
10061006

10071007
// Start Changestream Example 4
10081008
$pipeline = [['$match' => ['$or' => [['fullDocument.username' => 'alice'], ['operationType' => 'delete']]]]];

tests/Operation/WatchFunctionalTest.php

Lines changed: 7 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ public function testNextResumesAfterCursorNotFound()
5757
'documentKey' => ['_id' => 2],
5858
];
5959

60-
$this->assertSameDocument($expectedResult, $changeStream->current());
60+
$this->assertMatchesDocument($expectedResult, $changeStream->current());
6161

6262
$this->killChangeStreamCursor($changeStream);
6363

@@ -74,7 +74,7 @@ public function testNextResumesAfterCursorNotFound()
7474
'documentKey' => ['_id' => 3]
7575
];
7676

77-
$this->assertSameDocument($expectedResult, $changeStream->current());
77+
$this->assertMatchesDocument($expectedResult, $changeStream->current());
7878
}
7979

8080
public function testNextResumesAfterConnectionException()
@@ -203,7 +203,7 @@ public function testNoChangeAfterResumeBeforeInsert()
203203
'documentKey' => ['_id' => 2],
204204
];
205205

206-
$this->assertSameDocument($expectedResult, $changeStream->current());
206+
$this->assertMatchesDocument($expectedResult, $changeStream->current());
207207

208208
$this->killChangeStreamCursor($changeStream);
209209

@@ -224,7 +224,7 @@ public function testNoChangeAfterResumeBeforeInsert()
224224
'documentKey' => ['_id' => 3],
225225
];
226226

227-
$this->assertSameDocument($expectedResult, $changeStream->current());
227+
$this->assertMatchesDocument($expectedResult, $changeStream->current());
228228
}
229229

230230
public function testKey()
@@ -452,7 +452,7 @@ public function testRewindExtractsResumeTokenAndNextResumes()
452452
'ns' => ['db' => $this->getDatabaseName(), 'coll' => $this->getCollectionName()],
453453
'documentKey' => ['_id' => 1],
454454
];
455-
$this->assertSameDocument($expectedResult, $changeStream->current());
455+
$this->assertMatchesDocument($expectedResult, $changeStream->current());
456456

457457
$this->killChangeStreamCursor($changeStream);
458458

@@ -466,7 +466,7 @@ public function testRewindExtractsResumeTokenAndNextResumes()
466466
'ns' => ['db' => $this->getDatabaseName(), 'coll' => $this->getCollectionName()],
467467
'documentKey' => ['_id' => 2],
468468
];
469-
$this->assertSameDocument($expectedResult, $changeStream->current());
469+
$this->assertMatchesDocument($expectedResult, $changeStream->current());
470470
}
471471

472472
/**
@@ -484,16 +484,8 @@ public function testTypeMapOption(array $typeMap, $expectedChangeDocument)
484484

485485
$changeStream->next();
486486
$this->assertTrue($changeStream->valid());
487-
$changeDocument = $changeStream->current();
488-
489-
// Unset the resume token and namespace, which are intentionally omitted
490-
if (is_array($changeDocument)) {
491-
unset($changeDocument['_id'], $changeDocument['ns']);
492-
} else {
493-
unset($changeDocument->_id, $changeDocument->ns);
494-
}
495487

496-
$this->assertEquals($expectedChangeDocument, $changeDocument);
488+
$this->assertMatchesDocument($expectedChangeDocument, $changeStream->current());
497489
}
498490

499491
public function provideTypeMapOptionsAndExpectedChangeDocument()

tests/TestCase.php

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,49 @@ protected function assertDeprecated(callable $execution)
6969
$this->assertCount(1, $errors);
7070
}
7171

72+
/**
73+
* Asserts that a document has expected values for some fields.
74+
*
75+
* Only fields in the expected document will be checked. The actual document
76+
* may contain additional fields.
77+
*
78+
* @param array|object $expectedDocument
79+
* @param array|object $actualDocument
80+
*/
81+
protected function assertMatchesDocument($expectedDocument, $actualDocument)
82+
{
83+
$normalizedExpectedDocument = $this->normalizeBSON($expectedDocument);
84+
$normalizedActualDocument = $this->normalizeBSON($actualDocument);
85+
86+
$extraKeys = [];
87+
88+
/* Avoid unsetting fields while we're iterating on the ArrayObject to
89+
* work around https://bugs.php.net/bug.php?id=70246 */
90+
foreach ($normalizedActualDocument as $key => $value) {
91+
if ( ! $normalizedExpectedDocument->offsetExists($key)) {
92+
$extraKeys[] = $key;
93+
}
94+
}
95+
96+
foreach ($extraKeys as $key) {
97+
$normalizedActualDocument->offsetUnset($key);
98+
}
99+
100+
$this->assertEquals(
101+
\MongoDB\BSON\toJSON(\MongoDB\BSON\fromPHP($normalizedExpectedDocument)),
102+
\MongoDB\BSON\toJSON(\MongoDB\BSON\fromPHP($normalizedActualDocument))
103+
);
104+
}
105+
106+
/**
107+
* Asserts that a document has expected values for all fields.
108+
*
109+
* The actual document will be compared directly with the expected document
110+
* and may not contain extra fields.
111+
*
112+
* @param array|object $expectedDocument
113+
* @param array|object $actualDocument
114+
*/
72115
protected function assertSameDocument($expectedDocument, $actualDocument)
73116
{
74117
$this->assertEquals(

0 commit comments

Comments
 (0)