How initiate the server inside gitlab-runner? - node.js

I have my tests in TS with jest and supertest. Locally all works but inside the gitlab-runner (gitlab-ci) all falied because this:
TypeError: Cannot read property 'address' of undefined
This error is because don't find the server, but is there o_O
Only inside the runner apper this error.
An example of test:
beforeAll(async () => {
app = await Server.init();
});
afterAll(async () => {
await app.close();
});
test('it should return 200', async () => {
const res = await request(app).post(`${URL}/ok`).send(body);
expect(res.status).toEqual(200);
});
I'm export my listen server in the application. This tests is inside a describe.
Thanks

Related

error MongoNotConnectedError when running yield file from unit test nodeJs

I have a file that containt yield and co logic in node JS, the code look like below
module.export = {
moduleName(payload, callback){
//first logic
// second logic
co(function*(){
yield user.findById(somerandomid)
//error when find user by id
})
}
}
and this is my unit test code
beforeAll(async () => {
await dbHandler.connect();
//this part to connecto to mongodb
});
afterAll(async () => {
await dbHandler.disconnect();
});
afterEach(async () => {
jest.clearAllMocks();
});
it("test",()=>{
moduleName(somepayload)
})
so when i run my test case i got error :
MongoNotConnectedError: Client must be connected before running operations
i know this error because not connected to mongodb but i already create connection in beforeAll function, i have tried to wrap my connection in test case to yield like below
it('ts',async()=>{
co(function*(){
yield dbHandler.connect()
yield moduleName(somepayload)
}
})
but it did not work, any ideas?

Jest run code before and after all of the tests

I would like to run code before and after all the tests, not file wide, test wide. For example;
Before starting the e2e tests, I would like to run the server in test mode with the database. After all, I would like to flush my db and close the processes.
I don't know if it is possible but I also would like to have a global db variable to do tests. What I am currently doing is like this:
describe("Posts Module", () => {
let dbService: DatabaseService;
beforeAll(async () => {
dbService = new DatabaseService();
await dbService.init();
});
it("should give the posts", () => {
supertest(app)
.get("/posts")
.expect(200)
.then(async (response) => {
const dbPosts = await dbService.getPosts();
expect(response.body).toBeDefined();
expect(response.body.posts).toEqual(dbPosts);
});
});
afterAll(async () => {
await flushDb(dbService);
await dbService.close();
});
});
But what I actually want is initing this database service only once before all of the module tests (also starting the server, currently I start the server manually and run the tests afterwards).

Nodejs, Serverless expected stub function to be called once but was called 0 times

I have been the said error when trying to create a stub from sinon in my test function. I am trying to test a function responsible to make http calls to other endpoints. I am trying to understand why Its not resolving to the output provided.
const sinon = require('sinon');
const sandbox = sinon.createSandbox();
describe('test endpoint', () => {
it('should be test function', async () => {
const stub = sinon.stub(someServiceMock.POST, '/funcName').resolves({ status: 204 });
sinon.assert.calledOnce(stub);
});
});
});
and getting AssertError: expected '/funcName' to be called once but was called 0 times
The object i pass in the stub is
const someServiceMock = {
POST: {
'/funcName': () => {},
},
};
The stubbed function is never called in the code-sample you provided. If you actually call the funtion with
describe('test endpoint', () => {
it('should be test function', async () => {
const stub = sinon.stub(someServiceMock.POST, '/funcName').resolves({ status: 204 });
someServiceMock.POST["/funcName"]();
sinon.assert.calledOnce(stub);
});
});
the test should pass as expected.

Nodejs Jest mocking is not working in multiple describe block in a single file, it works in first describe block only

I am using jest for unit testing in my node express application,please excuse , because i am new to all this
in my abc.test.js
const s3Helper = require('../../../../../lib/s3_helper');
beforeEach(async () => {
s3Helper.uploadBufferToS3 = jest.fn(() => true);
});
describe('test1', () => {
it('test1', async () => {
expect(s3Helper.uploadBufferToS3)
.toHaveBeenCalled();
});
});
describe('test2', () => {
it('test2', async () => {
expect(s3Helper.uploadBufferToS3)
.toHaveBeenCalled();
});
});
so when i run this test file in test1 it returns that test is passed, however in test2 it returns expected >=1 returned 0.
since i am mocking it beforeEach i expect it should return 1 for each describe block

How to close Express server inside Jest afterAll hook

I am trying to write integration tests for my Express server using Jest. Since Jest runs tests in parallel (and I would like to avoid running tests in sequence using --runInBand), I am using the get-port library to find a random available port so that different test suites don't have port collisions.
My tests all run successfully, the only problem is that the server is failing to close down properly inside the afterAll hook. This causes Jest to print the following in the console...
Jest did not exit one second after the test run has completed.
This usually means that there are asynchronous operations that weren't stopped in your tests.
Consider running Jest with `--detectOpenHandles` to troubleshoot this issue.
When I use the --detectOpenHandles flag, Jest just hangs after tests complete. Nothing gets printed to the console.
Here is my test code...
let axios = require('axios')
const getPort = require('get-port')
const { app } = require('../../index')
const { Todo } = require('../../models')
// set reference to server to access
// from within afterAll hook
let server
beforeAll(async () => {
const port = await getPort()
axios = axios.create({ baseURL: `http://localhost:${port}` })
server = app.listen(port)
})
afterAll(() => {
server.close()
})
describe('GET /todos', () => {
it('returns a list of todos', async () => {
const { data: todos } = await axios.get('/todos')
todos.forEach(todo => {
expect(Todo.validate(todo)).toEqual(true)
})
})
})
I am on that github thread on this issue. Here is exactly the configuration that works for me. In package.json
"test": "jest --no-cache --detectOpenHandles --runInBand --forceExit",
Here is the configuration in test file
afterEach(async () => {
await server.close();
});
afterAll(async () => {
await new Promise(resolve => setTimeout(() => resolve(), 10000)); // avoid jest open handle error
});
beforeEach(() => {
// eslint-disable-next-line global-require
server = require('../index');
jest.setTimeout(30000);
});
OR you have only afterAll to set timeout and settimeout for each test in the test body individually.That's example below
afterEach(async () => {
await server.close();
});
afterAll(async () => {
await new Promise(resolve => setTimeout(() => resolve(), 10000)); // avoid jest open handle error
});
beforeEach(() => {
// eslint-disable-next-line global-require
server = require('../index');
});
describe('POST /customers', () => {
jest.setTimeout(30000);
test('It creates a customer', async () => {
const r = Math.random()
.toString(36)
.substring(7);
const response = await request(server)
.post('/customers')
.query({
name: r,
email: `${r}#${r}.com`,
password: 'beautiful',
});
// console.log(response.body);
expect(response.body).toHaveProperty('customer');
expect(response.body).toHaveProperty('accessToken');
expect(response.statusCode).toBe(200);
});
});
The root cause is that the express app server is still running after the tests complete. So the solution is to close the server.
In the main server file:
export const server = app.listen(...)
In the test file:
import { server } from './main-server-file'
afterAll(() => {
server.close();
});
Using nodejs 17.4.0, jest 27.5.1, supertest 6.2.2. Running test with
cross-env NODE_OPTIONS=--experimental-vm-modules NODE_ENV=test jest

Resources