port already in use
Add following line in app.js or main express server file
if (NODE_ENV !== 'test') {
await app.listen(PORT)
}
ref: ladjs/supertest#568 (comment)
if (NODE_ENV !== 'test') {
await mongoose.connect(CONNECTION_URI, OPTIONS)
}
const OLD_ENV = process.env;
beforeEach(() => {
jest.resetModules() // most important - it clears the cache
process.env = { ...OLD_ENV }; // make a copy
});
afterAll(() => {
process.env = OLD_ENV; // restore old env
});
ref: https://stackoverflow.com/a/48042799/3861525
import { MongoMemoryServer } from 'mongodb-memory-server'
import mongoose from 'mongoose'
const mongod = new MongoMemoryServer()
// can use it later in `beforeAll` callback
export async function initDB() {
const uri = await mongod.getConnectionString()
const mongooseOpts = {
useNewUrlParser: true,
autoReconnect: true,
reconnectTries: Number.MAX_VALUE,
reconnectInterval: 1000
}
await mongoose.connect(uri, mongooseOpts)
}
// can use it later in `afterAll` callback
export async function closeDB() {
await mongoose.connection.dropDatabase()
await mongoose.connection.close()
await mongod.stop()
}
// can use it later in `afterEach` callback
export async function cleanupDB() {
const collections = mongoose.connection.collections
for (const key in collections) {
const collection = collections[key]
await collection.deleteMany()
}
}
In this case, sendSms API calls external API like AWS SNS or Twilio using the server endpoint
use nock.cleanAll()
in afterAll callback and nock.restore()
in afterEach callback to make sure there are no side effects*
it('should return success with valid params', async (done) => {
// setup path for fixtures for recorded data
nock.back.fixtures = path.join(__dirname, 'fixtures')
...
...
nock.back.setMode('record')
const { nockDone } = await nock.back('aws-sms-request.json')
// to prevent recording localhost network request, can use it in `beforeAll` or `beforeEach`
nock.enableNetConnect(/127\.0\.0\.1/)
await request(app)
.post('/sendSms')
.send({
phoneNumber: ['1234567890'],
message: '123'
})
// to stop recording network requests using nock
await nockDone()
})
it('should return success with valid params', async (done) => {
await request(app)
.post('/sendSms')
.send({
phoneNumber: ['1234567890'],
message: '123'
})
done()
})
For instance we have a Crypto
module used in route sendSms
which generates random encrypted data
when we call Crypto.encrypt()
method then the response of the API endpoint will vary for every input,
to ensure our tests are passing for such cases we can mock Crypto.encrypt
in jest like below
import { Crypto } from '../src/helpers/Crypto'
const originalCrypto = Crypto.prototype.encrypt
// can be called in the `it` callback or beforeEach callback
function mockCrypto(value) {
Crypto.prototype.encrypt = jest.fn(() => value)
}
function clearEncryptoMock() {
Crypto.prototype.encrypt = originalEncrypto
}
function mockDateManager(defaultDate) {
const defaultDate = Date.now
return {
mockDate: () => Date.now = () => defaultDate
restoreDate: () => Date.now = defaultDate
}
const dateManager = mockDateManager(1595399185353)
...
// can use it in individual tests for more control
beforeEach(dateManager.mockDate)
afterEach(dateManager.restoreDate)
// package.json
"test": "mocha --recursive './test/*.js' --require esm"