'nodejs: Tests pass individually, fail when run together (mocha, sinon, aws-sdk)
I have tests that:
- PASS when run together in VS Code
- FAIL when run together on the CLI
- PASS when run individually (e.g.
mocha bogus.test.js -g "second")
Here's the code as bare bones as I can make it (and it's pretty darned bare bones):
const AWS = require("aws-sdk")
const SQS = new AWS.SQS()
exports.handler = () => {
return SQS.deleteMessage({foo: "bar"}).promise()
}
and the test:
const sinon = require("sinon")
const expect = require("chai").expect
const AWS = require("aws-sdk")
describe("Bogus Test", () => {
let sandbox, deleteMessageStub
beforeEach(() => {
sandbox = sinon.createSandbox()
deleteMessageStub = sandbox.fake.returns({ promise: () => Promise.resolve({}) })
sandbox.stub(AWS, 'SQS').returns({
deleteMessage: deleteMessageStub
})
})
afterEach(() => { sandbox.restore() })
it("is the first test", () => {
const bogus = require("../bogus")
return bogus.handler().then(() => {
expect(deleteMessageStub.callCount).to.equal(1, 'Should have called deleteMessage once')
})
})
it("is the second test", () => {
const bogus = require("../bogus")
return bogus.handler().then(() => {
expect(deleteMessageStub.callCount).to.equal(1, 'Should have called deleteMessage once')
})
})
})
Results:
Bogus Test
✓ is the first test
1) is the second test
1 passing (14ms)
1 failing
1) Bogus Test
is the second test:
Should have called deleteMessage once
+ expected - actual
-0
+1
at ... bogus.test.js:29:46
I would be DELIGHTED to find out that I'm doing something stupid...
Solution 1:[1]
require a module multiple times, the code of the module scope will only be executed once, because the module is cached in the require.cache object.
Which means the ./bogus module is only loaded once and is obtained from the require.cache object during the second require. The const SQS = new AWS.SQS(); statement will be executed only once.
You cleared the call information of the stub through ·sinon.restore()·, so the stub.callCount of the second test case is 0.
Solution: Clear the module cache of ./bogus within beforeEach() hook
E.g.
bogus.js:
const AWS = require('aws-sdk');
const SQS = new AWS.SQS();
exports.handler = () => {
return SQS.deleteMessage({ foo: 'bar' }).promise();
};
bogus.test.js:
const sinon = require('sinon');
const expect = require('chai').expect;
const AWS = require('aws-sdk');
describe('Bogus Test', () => {
let sandbox, deleteMessageStub;
beforeEach(() => {
sandbox = sinon.createSandbox();
deleteMessageStub = sandbox.fake.returns({ promise: () => Promise.resolve({}) });
sandbox.stub(AWS, 'SQS').returns({
deleteMessage: deleteMessageStub,
});
delete require.cache[require.resolve('./bogus')];
});
afterEach(() => {
sandbox.restore();
});
it('is the first test', () => {
const bogus = require('./bogus');
return bogus.handler().then(() => {
expect(deleteMessageStub.callCount).to.equal(1, 'Should have called deleteMessage once');
});
});
it('is the second test', () => {
const bogus = require('./bogus');
return bogus.handler().then(() => {
expect(deleteMessageStub.callCount).to.equal(1, 'Should have called deleteMessage once');
});
});
});
unit test result:
Bogus Test
? is the first test
? is the second test
2 passing (9ms)
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |
