How to optimize tests from multiple "act"? - jestjs

My tests are already working fine. But I'm a bit worried because I have still remaining 5 tests to make and it already consumed 5 seconds. There are five working testing, and one only using async
The code below shows that act is running on each tests. Even though I already mocked the api, I don't seem to see the difference because I think its consuming 1 second on each test.
I would like to ask advice or ask on how we could optimize it, so we could lessen the time execution? I already tried beforeAll but it will cause and error to other test.
describe('when using filter functions', () => {
describe('when using search function', () => {
beforeEach(async () => {
providerApi.getUsers.mockImplementationOnce(() => {
return Promise.resolve().then(() => {
return { data: testData.token }
})
})
await act(async () => {
render(
<Main>
<Home />
</Main>
)
})
})
afterEach(() => {
providerApi.getUsers.mockReset()
jest.clearAllMocks()
})
it('test #1', async () => {
const pagination = await screen.getByTestId('project-list')
...
});
it('test #2', () => { ... })
it('test #3', () => { ... })
it('test #4', () => { ... })
it('test #5', () => { ... })
});
});

Related

Jest await not working/returning anything test is frozen

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

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.

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?

Change jest mock on class for single test

I have an issue where I want to change what a class method returns for a single test while testing a different module. I have the following:
testingModule.test.js
const { testingModuleMethod } = require('../testingModule')
jest.mock('../helperClass', () =>
jest.fn().mockImplementation(() => ({
helperClassMethod: jest.fn()
}))
);
describe('testingModule.js', () => {
describe('testingModuleMethod', () => {
describe('when errors', () => {
const consoleSpy = jest.spyOn(console, 'error');
// SOMETHING NEEDS TO GO HERE TO CHANGE THE jest.mock ON LINE 3
await expect(testingModuleMethod(data)).rejects.toThrow('Error');
expect(consoleSpy).toHaveBeenCalled();
consoleSpy.mockRestore();
});
});
});
testingModule.js
const HelperClass = require('./helperClass');
const testingModuleMethod = async (data, callback) => {
try {
const objectToEvaluate = data.object;
const helperClassInstance = new HelperClass();
await helperClassInstance.helperClassMethod(objectToEvaluate);
log('info', "Success!");
callback(null, {});
} catch(error) {
log('error', 'Something went wrong')
}
};
No matter what I put in there I either get an error with the code (undefined) or it just ignores it and resolves due to the mock at the start. I have tried adding a spy as well as importing the class and using the prototype override.
I'm using node and "jest": "^27.0.6"
I have managed to answer this by doing the following:
Firstly I discovered that to mock a class like that I have to add a jest function into the mock like so:
describe('testingModuleMethod', () => {
describe('when errors', () => {
const consoleSpy = jest.spyOn(console, 'error');
HelperClass.mockImplementation(() => ({
helperClassMethod: jest.fn(() => { throw new Error('Error') })
}));
await expect(testingModuleMethod(data)).rejects.toThrow('Error');
expect(consoleSpy).toHaveBeenCalled();
consoleSpy.mockRestore();
});
});
This also had a knock on effect to the rest of the tests though so I added a beforeEach at the start that looks like:
HelperClass.mockImplementation(
jest.fn().mockImplementation(() => ({
helperClassMethod: jest.fn()
}))
);
Finally I needed to require the class. The overall test looks like this now and works:
const { testingModuleMethod } = require('../testingModule');
const HelperClass = require('./helperClass');
jest.mock('../helperClass', () =>
jest.fn().mockImplementation(() => ({
helperClassMethod: jest.fn()
}))
);
describe('testingModule.js', () => {
beforeEach(() => {
HelperClass.mockImplementation(
jest.fn().mockImplementation(() => ({
helperClassMethod: jest.fn()
}))
);
});
describe('testingModuleMethod', () => {
describe('when errors', () => {
const consoleSpy = jest.spyOn(console, 'error');
HelperClass.mockImplementation(() => ({
helperClassMethod: jest.fn(() => { throw new Error('Error') })
}));
await expect(testingModuleMethod(data)).rejects.toThrow('Error');
expect(consoleSpy).toHaveBeenCalled();
consoleSpy.mockRestore();
});
});
});

Testing promise with ava

I try to test this class
class Scraper {
async run() {
return await nightmare
.goto(this.url)
.wait('...')
.evaluate(()=>{...})
.end
}
}
And my test looks like this:
test('Scraper test', t => {
new Scraper().run().then(() => {
t.is('test', 'test')
})
})
Test fails:
Test finished without running any assertions
EDIT
repository on github: https://github.com/epyx25/test
test file: https://github.com/epyx25/test/blob/master/src/test/scraper/testScraper.test.js#L12
You need to return the promise. Assertion planning is not needed:
test('Scraper test', t => {
return new Scraper().run().then(() => {
t.is('test', 'test')
})
})
Or better still, using an async test:
test('Scraper test', async t => {
await new Scraper().run()
t.is('test', 'test')
})
you must using assert-planning to blocking the test until the lambda is notified by the Promise, for example:
test('Scraper test', t => {
t.plan(1);
return new Scraper().run().then(() => {
t.is('test', 'test')
})
})
OR
test.cb('Scraper test', t => {
t.plan(1);
new Scraper().run().then(() => {
t.is('test', 'test')
t.end()
})
})

Resources