Jest await not working/returning anything test is frozen - jestjs

I am trying to use await in my test and when I run the test runner the test becomes stuck and no test result is returned. Here is my code
describe("retrieveCandidate", () => {
describe("when settings are found", () => {
beforeEach(() => {
configurationApi = new ConfigurationApi(BaseUrl);
});
afterEach(() => {
configurationApi = undefined;
});
it("should return set of configuration values", () => {
const configurationValueSet: IConfigurationValueSet | undefined =
await configurationApi?.retrieveCandidate(controlConfigurationValueSet.specializationKey);
expect(true).toEqual(true);
});
});

So in my testsetup file I had
jest.useFakeTimers();
This caused my async functions to never return anything and caused my test to be in a frozen state

Related

sinon.stub isn't working in my api integration tests

i'm doing some integration tests in my API with mocha, chai, sinon and chai-http.
I made the tests for my post route and works fine, but, when I tried to do the same with my get route, the stub isn't workig. The code is bellow.
describe('Commentary API Test', () => {
describe('POST commentary', () => {
before(() => {
sinon.stub(CommentaryModel.prototype, 'add').resolves(newCommentaryResponse as any);
});
after(() => {
(CommentaryModel.prototype.add as SinonStub).restore();
});
it('should return status 201 and a new commentary json', async () => {
const response = await chai.request(app).post('/commentary').send(newCommentaryPayload)
expect(response).to.have.status(201);
expect(response.body).to.be.deep.equal(newCommentaryResponse);
});
it('should return error 400 with incorrect payload and a message', async () => {
const response = await chai.request(app).post('/commentary').send(newCommentaryPayload.pokemonName);
expect(response).to.have.status(400);
expect(response.body).to.be.deep.equal({"message":"All fields must be correctly filled"});
});
});
describe("GET commentaries", () => {
before(() => {
sinon.stub(CommentaryModel.prototype, 'get').resolves(1 as any);
});
after(() => {
(CommentaryModel.prototype.get as SinonStub).restore();
});
})
it('should return status 200 and a array with commentaries', async () => {
const response = await chai.request(app).get('/commentary');
console.log(response.body)
expect(response).to.have.status(200);
expect(response.body).to.be.equal(commentaryArray);
});
});
I put the number 1 as response, but i still getting a array with the pokemon infos... any idea why this stub isn't working?
Change the stub values some times.

Postgres, Node, Jest - Splitting testes into two suites results in deadlock

I have two suites of tests, one for Accounts and one for Transactions, accounts.spec.js and transactions.spec.js. I'm also using supertest.
When I run them in jest, I get the error error: deadlock detected.
But if I move all describe blocks to one single spec.js file, and run only that file in jest, I get no errors.
The Account router is:
accountRouter.js
router.get('/accounts', async (req, res) => {
const result = await pool.query('SELECT * FROM accounts')
if (result.rows.length > 0) {
return res.status(200).send({ accounts: result.rows })
} else {
return res.status(404).send({ msg: 'No Account Found' })
}
})
And the Account test file is:
accounts.spec.js
describe('Accounts', () => {
beforeAll(() => {
return pool.query('BEGIN')
})
afterAll(() => {
return pool.query('ROLLBACK')
})
afterEach(() => {
return pool.query('TRUNCATE accounts')
})
it('returns 200 and all accounts', async () => {
await request(app).post(`${apiURL}/accounts`).send({title: 'Investments',})
const response = await request(app).get(`${apiURL}/accounts`).send()
expect(response.status).toBe(200)
expect(response.body.accounts.length).toBe(1)
});
})
The Transactions router is:
transactionsRouter.js
router.get('/:id/deposit', async (req, res) => {
const id = req.params.id
const result = await pool.query('SELECT * FROM accounts WHERE acc_id = ($1)', [id])
if (result.rows.length > 0) {
return res.status(200).send({destinationAccount: result.rows[0]})
} else {
return res.status(404).send({validationErrors: {invalidId: 'Account Not Found'}})
})
And the Transactions test file is:
transactions.spec.js
describe('Transactions DEPOSIT', () => {
beforeAll(() => {
return pool.query('BEGIN')
})
afterAll(() => {
return pool.query('ROLLBACK')
})
afterEach(() => {
return pool.query('TRUNCATE accounts')
})
afterEach(() => {
return pool.query('TRUNCATE transactions')
})
it('DEPOSIT returns 200 OK and account by id', async () => {
const insertMockAccountQuery = 'INSERT INTO accounts (title) VALUES ($1) RETURNING acc_id, title, budget';
const mockAccount = await pool.query(insertMockAccountQuery, [title])
const existingAccount = mockAccount.rows[0];
const response = await request(app).get(`${apiURL}/transactions/${existingAccount.acc_id}/deposit`).send();
expect(response.status).toBe(200);
expect(response.body.destinationAccount).toEqual(existingAccount);
})
});
Can anyone help me figure out the problem, please?
Thanks
Jest runs tests from one describe sequentially. Whereas runs tests from multiple files simultaneously.
In order to run all the tests sequentially the CLI flag --runInBand could be used.
More details here:
Are tests inside one file run in parallel in Jest?

Jest, 2 describe make timeOut in test with 2 beforeEach mockClear()

I have a test file like this:
const axios = require('axios')
const Vacations = require('../../soap/vacationsSoap')
jest.mock('axios')
describe('describe a', () => {
beforeEach(() => { axios.default.post.mockClear() })
it('some it a.1', () => {
expect(Vacations.getReadXML()).toBe('something')
})
})
describe('describe b', () => {
beforeEach(() => { axios.default.post.mockClear() })
it('some it b.1', async () => {
axios.default.post.mockResolvedValueOnce({ data: 'sth' })
const client = new Vacations()
await expect(client.save()).rejects.toThrow('some error')
})
})
When I run the test, it gets hangout until I get a timeOut error.
But, if I remove the:
beforeEach(() => { axios.default.post.mockClear() })
from the second "describe" it works ok.
I copy pasted the while body from the describe 1 into 2, that's why I thought that it would works with the beforeEach. Why is happening that?

how do I test node.js template render in jest

This is one of my routes.
const actor = await Actor.findById(req.params.id);
if(!actor) throw new Error("Actor not found");
res.render('admin/actors/edit_actor',{actor:actor});
The thing is I don't know how to test if valid actor gets returned because of render function.
================================================================
If I write the following
const actor = await Actor.findById(req.params.id);
if(!actor) throw new Error("Actor not found");
res.send({actor:actor});
I know how to test this because this actor would be in body parameters. such as:
//test
const res = await request(server).get('/actor/2');
res.body is the same as actor
So questions:
1) how do I test the first example which renders some view?
2) first example to test there's an integration test needed. and for the second example, we should write functional test. Am I right?
In an unit test you're supposed to mock your dependencies, so if you're testing your controller you should mock the req and res objects as well as the model. For example
Implementation
import Actor from '../model/Actor';
const controller = (req, res) => {
const actor = await Actor.findById(req.params.id);
if(!actor) throw new Error("Actor not found");
res.render('admin/actors/edit_actor',{actor:actor});
}
Unit Test
import Actor from '../model/Actor';
jest.mock('../model/Actor');
describe('controller', () => {
const req = {
params: { id: 101 }
};
const res. = {
render: jest.fn()
};
beforeAll(() => {
Actor.findById.mockClear();
controller(req, res);
});
describe('returning an actor', () => {
beforeAll(() => {
res.render.mockClear();
Actor.findById.mockResolvedValue({
name: "Some Actor"
});
controller(req, res);
});
it('should get actor by id', () => {
expect(Actor.findById).toHaveBeenCalledWith(101);
});
it('should call res.render', () => {
expect(res.render).toHaveBeenCalledWith('admin/actors/edit_actor', { actor });
})
});
describe('not returning an actor', () => {
beforeAll(() => {
res.render.mockClear();
Actor.findById.mockResolvedValue(undefined);
controller(req, res);
});
it('should throw an Error', () => {
expect(() => controller(req, res)).toThrow(Error);
});
it('should not call res.render', () => {
expect(res.render).not.toHaveBeenCalled();
});
});
});

Mocha test runner with external files - hooks run in different order?

I am trying to organise my mocha tests to run through a separate test runner. Whenever I run the test, console.log outputs a proper connection in the top level before block, but straight after outputs me null in the separate required file it block. The hook is being executed, and it sets the connection variable correctly, but somehow it does not get passed to the required file.
How come the connection does not get properly set? Confusingly, according to my debugger it block is executed before the before hook which contradicts the order of console.logs I see
describe.only('test-suite', async () => {
let connection; // undefinded at this point
before(async () => {
connection = await getConnection();
console.log(connection); -> proper connection instance
});
after(async () => {
await closeConnection();
});
require('./some/test')(
connection
);
});
./some/test.js
module.exports = async (
connection,
) => {
describe('my-method', async () => {
it('does things', async () => {
console.log(connection); // somehow undefined
});
});
};
This is because of the way JS handles references to objects. Reassigning the variable does not just change the value the reference points to, but instead creates a brand new reference pointing to a brand new value.
This is the workaround:
describe.only('test-suite', async () => {
let options = { connection: null};
before(async () => {
options.connection = await getConnection();
console.log(connection);
});
after(async () => {
await closeConnection();
});
require('./some/test')(
options
);
});
./some/test.js
module.exports = async (
options,
) => {
describe('my-method', async () => {
it('does things', async () => {
console.log(options.connection);
});
});
};

Resources