Skip to content

Commit 384bd91

Browse files
committed
test: move existing int tests to unit
1 parent d9206e8 commit 384bd91

File tree

3 files changed

+450
-344
lines changed

3 files changed

+450
-344
lines changed

src/change_stream.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -752,7 +752,7 @@ export class ChangeStream<
752752
try {
753753
await this.close();
754754
} catch (error) {
755-
// we're not concerned with errors from close()
755+
// We're not concerned with errors from close()
756756
}
757757
}
758758
}

test/integration/change-streams/change_stream.test.ts

Lines changed: 68 additions & 135 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,12 @@ import { promisify } from 'util';
1010
import {
1111
AbstractCursor,
1212
ChangeStream,
13+
ChangeStreamDocument,
1314
ChangeStreamOptions,
1415
Collection,
1516
CommandStartedEvent,
1617
Db,
1718
Long,
18-
MongoAPIError,
1919
MongoChangeStreamError,
2020
MongoClient,
2121
MongoServerError,
@@ -989,137 +989,45 @@ describe('Change Streams', function () {
989989
async function () {
990990
changeStream = collection.watch([]);
991991
await initIteratorMode(changeStream);
992-
const changeStreamIterator = changeStream[Symbol.asyncIterator]();
993992

994993
const docs = [{ city: 'New York City' }, { city: 'Seattle' }, { city: 'Boston' }];
995994
await collection.insertMany(docs);
996995

997-
for (const doc of docs) {
998-
const change = await changeStreamIterator.next();
999-
const { fullDocument } = change.value;
1000-
expect(fullDocument.city).to.equal(doc.city);
996+
for await (const change of changeStream) {
997+
const { fullDocument } = change;
998+
const expectedDoc = docs.shift();
999+
expect(fullDocument.city).to.equal(expectedDoc.city);
1000+
if (docs.length === 0) {
1001+
break;
1002+
}
10011003
}
1004+
expect(docs).to.have.length(0, 'expected to find all docs before exiting loop');
10021005
}
10031006
);
10041007

10051008
it(
1006-
'should close the change stream when return is called',
1009+
'cannot resume from partial iteration',
10071010
{ requires: { topology: '!single' } },
10081011
async function () {
10091012
changeStream = collection.watch([]);
10101013
await initIteratorMode(changeStream);
1011-
const changeStreamIterator = changeStream[Symbol.asyncIterator]();
10121014

10131015
const docs = [{ city: 'New York City' }, { city: 'Seattle' }, { city: 'Boston' }];
10141016
await collection.insertMany(docs);
10151017

1016-
await changeStreamIterator.next();
1017-
await changeStreamIterator.return();
1018-
expect(changeStream.closed).to.be.true;
1019-
expect(changeStream.cursor.closed).to.be.true;
1020-
}
1021-
);
1022-
1023-
it(
1024-
'should close the change stream when an error is thrown',
1025-
{ requires: { topology: '!single', mongodb: '>=4.2' } },
1026-
async function () {
1027-
changeStream = collection.watch([]);
1028-
await initIteratorMode(changeStream);
1029-
const changeStreamIterator = changeStream[Symbol.asyncIterator]();
1030-
1031-
const unresumableErrorCode = 1000;
1032-
await client.db('admin').command({
1033-
configureFailPoint: is4_2Server(this.configuration.version)
1034-
? 'failCommand'
1035-
: 'failGetMoreAfterCursorCheckout',
1036-
mode: { times: 1 },
1037-
data: {
1038-
failCommands: ['getMore'],
1039-
errorCode: unresumableErrorCode
1040-
}
1041-
} as FailPoint);
1042-
1043-
await collection.insertOne({ city: 'New York City' });
1044-
try {
1045-
await changeStreamIterator.next();
1046-
expect.fail(
1047-
'Change stream did not throw unresumable error and did not produce any events'
1048-
);
1049-
} catch (error) {
1050-
expect(changeStream.closed).to.be.true;
1051-
expect(changeStream.cursor.closed).to.be.true;
1018+
for await (const change of changeStream) {
1019+
const { fullDocument } = change;
1020+
const expectedDoc = docs.shift();
1021+
expect(fullDocument.city).to.equal(expectedDoc.city);
1022+
break;
10521023
}
1053-
}
1054-
);
1055-
1056-
it(
1057-
'should not produce events on closed stream',
1058-
{ requires: { topology: '!single' } },
1059-
async function () {
1060-
changeStream = collection.watch([]);
1061-
changeStream.close();
10621024

1063-
const changeStreamIterator = changeStream[Symbol.asyncIterator]();
1064-
const change = await changeStreamIterator.next();
1065-
1066-
expect(change.value).to.be.undefined;
1067-
}
1068-
);
1069-
1070-
it(
1071-
'cannot be used with emitter-based iteration',
1072-
{ requires: { topology: '!single' } },
1073-
async function () {
1074-
changeStream = collection.watch([]);
1075-
changeStream.on('change', sinon.stub());
1076-
const changeStreamIterator = changeStream[Symbol.asyncIterator]();
1077-
1078-
const error = await changeStreamIterator.next().catch(e => e);
1079-
expect(error).to.be.instanceOf(MongoAPIError);
1080-
}
1081-
);
1082-
1083-
it(
1084-
'can be used with raw iterator API',
1085-
{ requires: { topology: '!single' } },
1086-
async function () {
1087-
changeStream = collection.watch([]);
1088-
await initIteratorMode(changeStream);
1089-
const changeStreamIterator = changeStream[Symbol.asyncIterator]();
1090-
1091-
const docs = [{ city: 'Los Angeles' }, { city: 'Miami' }];
1092-
await collection.insertMany(docs);
1093-
1094-
await changeStream.next();
1095-
1096-
try {
1097-
const change = await changeStreamIterator.next();
1098-
expect(change.value).to.not.be.undefined;
1099-
1100-
const { fullDocument } = change.value;
1101-
expect(fullDocument.city).to.equal(docs[1].city);
1102-
} catch (error) {
1103-
expect.fail('Async could not be used with raw iterator API');
1025+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
1026+
for await (const change of changeStream) {
1027+
expect.fail('Change stream resumed from partial iteration');
11041028
}
1105-
}
1106-
);
11071029

1108-
it(
1109-
'ignores errors thrown from close',
1110-
{ requires: { topology: '!single' } },
1111-
async function () {
1112-
changeStream = collection.watch([]);
1113-
await initIteratorMode(changeStream);
1114-
const changeStreamIterator = changeStream[Symbol.asyncIterator]();
1115-
1116-
sinon.stub(changeStream.cursor, 'close').throws(new MongoAPIError('testing'));
1117-
1118-
try {
1119-
await changeStreamIterator.return();
1120-
} catch (error) {
1121-
expect.fail('Async iterator threw an error on close');
1122-
}
1030+
expect(docs).to.have.length(2, 'expected to find remaining docs after partial iteration');
11231031
}
11241032
);
11251033
});
@@ -2352,7 +2260,6 @@ describe('ChangeStream resumability', function () {
23522260
async function () {
23532261
changeStream = collection.watch([]);
23542262
await initIteratorMode(changeStream);
2355-
const changeStreamIterator = changeStream[Symbol.asyncIterator]();
23562263

23572264
await client.db('admin').command({
23582265
configureFailPoint: is4_2Server(this.configuration.version)
@@ -2366,10 +2273,18 @@ describe('ChangeStream resumability', function () {
23662273
}
23672274
} as FailPoint);
23682275

2369-
await collection.insertOne({ city: 'New York City' });
2370-
await changeStreamIterator.next();
2276+
const docs = [{ city: 'New York City' }, { city: 'Seattle' }, { city: 'Boston' }];
2277+
await collection.insertMany(docs);
23712278

2372-
expect(aggregateEvents).to.have.lengthOf(2);
2279+
for await (const change of changeStream) {
2280+
const { fullDocument } = change;
2281+
const expectedDoc = docs.shift();
2282+
expect(fullDocument.city).to.equal(expectedDoc.city);
2283+
if (docs.length === 0) {
2284+
break;
2285+
}
2286+
}
2287+
expect(docs).to.have.length(0, 'expected to find all docs before exiting loop');
23732288
}
23742289
);
23752290
}
@@ -2383,12 +2298,15 @@ describe('ChangeStream resumability', function () {
23832298
await initIteratorMode(changeStream);
23842299
const changeStreamIterator = changeStream[Symbol.asyncIterator]();
23852300

2301+
const docs = [{ city: 'New York City' }, { city: 'Seattle' }, { city: 'Boston' }];
2302+
await collection.insertMany(docs);
2303+
23862304
// on 3.6 servers, no postBatchResumeToken is sent back in the initial aggregate response.
23872305
// This means that a resume token isn't cached until the first change has been iterated.
23882306
// In order to test the resume, we need to ensure that at least one document has
23892307
// been iterated so we have a resume token to resume on.
2390-
await collection.insertOne({ city: 'New York City' });
23912308
await changeStreamIterator.next();
2309+
docs.shift();
23922310

23932311
const mock = sinon
23942312
.stub(changeStream.cursor, '_getMore')
@@ -2399,10 +2317,16 @@ describe('ChangeStream resumability', function () {
23992317
callback(error);
24002318
});
24012319

2402-
await collection.insertOne({ city: 'New York City' });
2403-
await changeStreamIterator.next();
2320+
for await (const change of changeStream) {
2321+
const { fullDocument } = change;
2322+
const expectedDoc = docs.shift();
2323+
expect(fullDocument.city).to.equal(expectedDoc.city);
2324+
if (docs.length === 0) {
2325+
break;
2326+
}
2327+
}
24042328

2405-
expect(aggregateEvents).to.have.lengthOf(2);
2329+
expect(docs).to.have.length(0, 'expected to find all docs before exiting loop');
24062330
}
24072331
);
24082332
}
@@ -2447,25 +2371,34 @@ describe('ChangeStream resumability', function () {
24472371
async function () {
24482372
changeStream = collection.watch([]);
24492373
await initIteratorMode(changeStream);
2450-
const changeStreamIterator = changeStream[Symbol.asyncIterator]();
24512374

2452-
const unresumableErrorCode = 1000;
2453-
await client.db('admin').command({
2454-
configureFailPoint: is4_2Server(this.configuration.version)
2455-
? 'failCommand'
2456-
: 'failGetMoreAfterCursorCheckout',
2457-
mode: { times: 1 },
2458-
data: {
2459-
failCommands: ['getMore'],
2460-
errorCode: unresumableErrorCode
2461-
}
2462-
} as FailPoint);
2375+
const docs = [{ city: 'New York City' }, { city: 'Seattle' }, { city: 'Boston' }];
2376+
await collection.insertMany(docs);
24632377

2464-
await collection.insertOne({ city: 'New York City' });
2378+
try {
2379+
for await (const change of changeStream) {
2380+
const { fullDocument } = change;
2381+
const expectedDoc = docs.shift();
2382+
expect(fullDocument.city).to.equal(expectedDoc.city);
2383+
2384+
const unresumableErrorCode = 1000;
2385+
await client.db('admin').command({
2386+
configureFailPoint: is4_2Server(this.configuration.version)
2387+
? 'failCommand'
2388+
: 'failGetMoreAfterCursorCheckout',
2389+
mode: { times: 1 },
2390+
data: {
2391+
failCommands: ['getMore'],
2392+
errorCode: unresumableErrorCode
2393+
}
2394+
} as FailPoint);
2395+
}
24652396

2466-
const error = await changeStreamIterator.next().catch(e => e);
2467-
expect(error).to.be.instanceOf(MongoServerError);
2468-
expect(aggregateEvents).to.have.lengthOf(1);
2397+
expect.fail('Async did not throw on an unresumable error');
2398+
} catch (error) {
2399+
expect(error).to.be.instanceOf(MongoServerError);
2400+
expect(aggregateEvents).to.have.lengthOf(1);
2401+
}
24692402
}
24702403
);
24712404
});

0 commit comments

Comments
 (0)