Skip to content

Commit

Permalink
spy instead of injecting
Browse files Browse the repository at this point in the history
  • Loading branch information
baileympearson committed Sep 4, 2024
1 parent 46e779d commit c169e58
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 34 deletions.
11 changes: 2 additions & 9 deletions src/cmap/wire_protocol/on_demand/document.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import {
Binary,
BSON,
type BSONElement,
BSONError,
type BSONSerializeOptions,
BSONType,
deserialize,
getBigInt64LE,
getFloat64LE,
getInt32LE,
Expand Down Expand Up @@ -46,13 +46,6 @@ type CachedBSONElement = { element: BSONElement; value: any | undefined };

/** @internal */
export class OnDemandDocument {
/**
* @internal
*
* Used for testing purposes.
*/
private static BSON: typeof BSON = BSON;

/**
* Maps JS strings to elements and jsValues for speeding up subsequent lookups.
* - If `false` then name does not exist in the BSON document
Expand Down Expand Up @@ -344,7 +337,7 @@ export class OnDemandDocument {
index: this.offset,
allowObjectSmallerThanBufferSize: true
};
return OnDemandDocument.BSON.deserialize(this.bson, exactBSONOptions);
return deserialize(this.bson, exactBSONOptions);
}

private parseBsonSerializationOptions(options?: { enableUtf8Validation?: boolean }): {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ import {
type Collection,
deserialize,
type MongoClient,
MongoDBResponse,
MongoServerError,
OnDemandDocument,
OpMsgResponse
} from '../../../mongodb';

Expand All @@ -28,12 +28,12 @@ describe('class MongoDBResponse', () => {
let bsonSpy: sinon.SinonSpy;

beforeEach(() => {
bsonSpy = sinon.spy(MongoDBResponse.prototype, 'parseBsonSerializationOptions');
// @ts-expect-error private function
bsonSpy = sinon.spy(OnDemandDocument.prototype, 'parseBsonSerializationOptions');
});

afterEach(() => {
bsonSpy?.restore();
// @ts-expect-error: Allow this to be garbage collected
bsonSpy = null;
});

Expand Down Expand Up @@ -159,7 +159,7 @@ describe('class MongoDBResponse', () => {
);
});

describe('utf8 validation with cursors' + i, function () {
describe('utf8 validation with cursors', function () {
let client: MongoClient;
let collection: Collection;

Expand Down
45 changes: 24 additions & 21 deletions test/unit/cmap/wire_protocol/responses.test.ts
Original file line number Diff line number Diff line change
@@ -1,28 +1,31 @@
import * as SPYABLE_BSON from 'bson';
import { expect } from 'chai';
import * as sinon from 'sinon';

// to spy on the bson module, we must import it from the driver
// eslint-disable-next-line @typescript-eslint/no-restricted-imports
import * as mdb from '../../../../src/bson';
import {
BSON,
CursorResponse,
Int32,
MongoDBResponse,
MongoUnexpectedServerResponseError,
OnDemandDocument
OnDemandDocument,
serialize
} from '../../../mongodb';

describe('class MongoDBResponse', () => {
it('is a subclass of OnDemandDocument', () => {
expect(new MongoDBResponse(BSON.serialize({ ok: 1 }))).to.be.instanceOf(OnDemandDocument);
expect(new MongoDBResponse(serialize({ ok: 1 }))).to.be.instanceOf(OnDemandDocument);
});

context('utf8 validation', () => {
let deseriailzeSpy: sinon.SinonSpy;
let deseriailzeSpy: sinon.SinonStub<Parameters<typeof mdb.deserialize>>;
beforeEach(function () {
// @ts-expect-error accessing internal property.
OnDemandDocument.BSON = SPYABLE_BSON;

deseriailzeSpy = sinon.spy(SPYABLE_BSON, 'deserialize');
const deserialize = mdb.deserialize;
deseriailzeSpy = sinon.stub<Parameters<typeof deserialize>>().callsFake(deserialize);
sinon.stub(mdb, 'deserialize').get(() => {
return deseriailzeSpy;
});
});
afterEach(function () {
sinon.restore();
Expand All @@ -31,7 +34,7 @@ describe('class MongoDBResponse', () => {
context('when enableUtf8Validation is not specified', () => {
const options = { enableUtf8Validation: undefined };
it('calls BSON deserialize with writeErrors validation turned off', () => {
const res = new MongoDBResponse(BSON.serialize({}));
const res = new MongoDBResponse(serialize({}));
res.toObject(options);

expect(deseriailzeSpy).to.have.been.called;
Expand All @@ -49,7 +52,7 @@ describe('class MongoDBResponse', () => {
context('when enableUtf8Validation is true', () => {
const options = { enableUtf8Validation: true };
it('calls BSON deserialize with writeErrors validation turned off', () => {
const res = new MongoDBResponse(BSON.serialize({}));
const res = new MongoDBResponse(serialize({}));
res.toObject(options);

expect(deseriailzeSpy).to.have.been.called;
Expand All @@ -67,7 +70,7 @@ describe('class MongoDBResponse', () => {
context('when enableUtf8Validation is false', () => {
const options = { enableUtf8Validation: false };
it('calls BSON deserialize with all validation disabled', () => {
const res = new MongoDBResponse(BSON.serialize({}));
const res = new MongoDBResponse(serialize({}));
res.toObject(options);

expect(deseriailzeSpy).to.have.been.called;
Expand All @@ -87,7 +90,7 @@ describe('class MongoDBResponse', () => {
describe('class CursorResponse', () => {
describe('get cursor()', () => {
it('throws if input does not contain cursor embedded document', () => {
expect(() => new CursorResponse(BSON.serialize({ ok: 1 })).cursor).to.throw(
expect(() => new CursorResponse(serialize({ ok: 1 })).cursor).to.throw(
MongoUnexpectedServerResponseError,
/"cursor" is missing/
);
Expand All @@ -96,7 +99,7 @@ describe('class CursorResponse', () => {

describe('get id()', () => {
it('throws if input does not contain cursor.id int64', () => {
expect(() => new CursorResponse(BSON.serialize({ ok: 1, cursor: {} })).id).to.throw(
expect(() => new CursorResponse(serialize({ ok: 1, cursor: {} })).id).to.throw(
MongoUnexpectedServerResponseError,
/"id" is missing/
);
Expand All @@ -107,22 +110,22 @@ describe('class CursorResponse', () => {
it('throws if input does not contain firstBatch nor nextBatch', () => {
expect(
// @ts-expect-error: testing private getter
() => new CursorResponse(BSON.serialize({ ok: 1, cursor: { id: 0n, batch: [] } })).batch
() => new CursorResponse(serialize({ ok: 1, cursor: { id: 0n, batch: [] } })).batch
).to.throw(MongoUnexpectedServerResponseError, /did not contain a batch/);
});
});

describe('get ns()', () => {
it('sets namespace to null if input does not contain cursor.ns', () => {
expect(new CursorResponse(BSON.serialize({ ok: 1, cursor: { id: 0n, firstBatch: [] } })).ns)
.to.be.null;
expect(new CursorResponse(serialize({ ok: 1, cursor: { id: 0n, firstBatch: [] } })).ns).to.be
.null;
});
});

describe('get batchSize()', () => {
it('reports the returned batch size', () => {
const response = new CursorResponse(
BSON.serialize({ ok: 1, cursor: { id: 0n, nextBatch: [{}, {}, {}] } })
serialize({ ok: 1, cursor: { id: 0n, nextBatch: [{}, {}, {}] } })
);
expect(response.batchSize).to.equal(3);
expect(response.shift()).to.deep.equal({});
Expand All @@ -133,7 +136,7 @@ describe('class CursorResponse', () => {
describe('get length()', () => {
it('reports number of documents remaining in the batch', () => {
const response = new CursorResponse(
BSON.serialize({ ok: 1, cursor: { id: 0n, nextBatch: [{}, {}, {}] } })
serialize({ ok: 1, cursor: { id: 0n, nextBatch: [{}, {}, {}] } })
);
expect(response).to.have.lengthOf(3);
expect(response.shift()).to.deep.equal({});
Expand All @@ -146,7 +149,7 @@ describe('class CursorResponse', () => {

beforeEach(async function () {
response = new CursorResponse(
BSON.serialize({
serialize({
ok: 1,
cursor: { id: 0n, nextBatch: [{ _id: 1 }, { _id: 2 }, { _id: 3 }] }
})
Expand All @@ -173,7 +176,7 @@ describe('class CursorResponse', () => {

beforeEach(async function () {
response = new CursorResponse(
BSON.serialize({
serialize({
ok: 1,
cursor: { id: 0n, nextBatch: [{ _id: 1 }, { _id: 2 }, { _id: 3 }] }
})
Expand Down

0 comments on commit c169e58

Please sign in to comment.