SQL query does not execute in afterAll() function while writing test cases - javascript

I am writing unit test cases using Protractor, Jasmine.
I have a code written in beforeAll() functions which sets up data by fetching from database using sql queries
Similarly, there is an afterAll() function whose task is to reset the data in database as it was before the test cases executed
beforeAll(() => {
//get database connection
// setup database data
});
it('should .....', () => {
//code
});
afterAll(() => {
// we can cleanup the database after we're done running our tests
cleanup.clearAlerts(connection)
.then(data => {
//code
});
});
Here the beforeAll() functions executes sql queries correctly
However, the afterAll() function just doesn't execute any cleanup sql queries.

Do some browser action in afterall to overcome the problem.
like
afterAll(async function () {
//your sql query here
await browser.waitForAngularEnabled(false);
await browser.get(browser.baseUrl);
});
Hope it help you.

Related

Creating single knex connection pool for all tests in jest

I use knex in my project and I try to write tests with it (with jest). I want to execute some scripts before each test and after each test, so each test will run on the same data in db.
I tried to create a global connection pool with knex, and execute the scripts in the tests setup. The problem is when I have tests in different describe scope.
For example, lets say I have 2 tests, each test is in different describe scope
import { connection } from './global-setup.ts'
describe('first', () => {
beforeEach( async () => {
await connection.raw(...)
}
afterEach( async () => {
await connection.raw(...)
}
it('test1', () => {...})
}
and same for the second test. The result is that the scripts in beforeEach is not always run, And as a result the second tests sometimes pass, and sometimes fail.
I did noticed that the connection pool is initalized every time for different describe scope, which I think is the cause of the problem. (and if I put the first and the second test in the same describe scope they always pass)
How can I fix this? or how can I make one connection pool for all the describe tests?

Problems getting Mocha tests to wait for db to be built

I have the following code which is designed to create a test db, upgrade it, seed it with data and then run a bunch of mocha tests:-
await createDatabase().then(async () => {
console.log("upgrading database");
await dbUpgrade().then(async () => {
console.log("seeding database");
await seedTestDatabase().then(() => {
After "seedTestDatabase", I call all my test suites. When I run this code, I get the following in the console:-
Opening database ./db/test.sqlite
listening on port 4001
creating database
upgrading database
starting upgrade
0 passing (1ms)
finished upgrade
seeding database
seeding test database
starting tests
For some reason, Mocha decides in the middle of the db upgrade function that it can't find any tests! If I run the functions createDatabase, dbUpgrade then seedDatabase manually one by one, everything works. What's going on with Mocha?
probably, it can work with mochajs
describe('test database is build', function(){
this.timeout(60 * 1000); // mocha terminates tests after 3 seconds with timeout error
it('creates database', function() {
return createDatabase();
});
it('updates database', function() {
return dbUpgrade();
});
it('seeds database', function() {
return seedTestDatabase();
});
});
if we assume each function depicted in question returns promise, we can call all them as test suit items in promise style approach sequently

Async Mocha done() isn't called in my function

I call this function, console log is called but done() is not called:
import {Database} from "../../code/server/Database";
import 'mocha'
const expect = require('chai').expect
describe('Database save', function() {
it('should save without error', function(done) {
Database.saveSessionData(1, 2, 3, function(err, docs) {
expect(err).to.equal(null)
expect(docs.sessionOpenTime).to.equal(1)
expect(docs.sessionCloseTime).to.equal(2)
expect(docs.sessionLength).to.equal(3)
console.log(2222)
done()
})
})
})
Here is the result, 'Running tests' continues spinning on forever:
But if I change the 'Database' code into this, it works as expected:
setTimeout(function () {
console.log('lol')
done()
}, 1000)
What am I missing here?
Mocha test hangs since you have an opened database connection.
There are two options to solve this problem:
If you do not need a real database connection in your tests:
you can use sinon.stub() (https://www.npmjs.com/package/sinon) to return a predetermined response for async methods you use in your tests or sinon.spy() to make sure a stubbed method called exact number of times.
Here's a good article I just found to illustrate how to use sinon.js: https://semaphoreci.com/community/tutorials/best-practices-for-spies-stubs-and-mocks-in-sinon-js.
you can implement a dependency injection container to be able to replace your implementation of Database class to a Database class that does not perform I/O operations.
Although dependency injection implementations may vary depending on requirements some simple implementations are also available:
https://blog.risingstack.com/dependency-injection-in-node-js/
If you need to perform a real connection in your tests:
Consider adding an after hook to your mocha tests:
let's say mongodb is used as a database (it does not matter, but it would
be an actual working example)
const mongoose = require('mongoose');
const expect = require('chai').expect;
mongoose.connect('mongodb://localhost/test');
after(() => {
mongoose.connection.close();
});
describe('db connection', () => {
it('should make a test', () => {
expect(1).to.equal(1);
});
});

Mocha change timeout for afterEach

I am writing a node application with mocha and chai. Some of the tests call an external API for integration tests, which might take up to 90sec to perform the action.
In order to cleanup properly, I defined an afterEach()-block, which will delete any generated remote resources, in case an expect fails and some resources weren't deleted.
The tests themselves have an increased timeout, while the rest of the tests should retain their default and small timeout:
it('should create remote resource', () => {...}).timeout(120000)
However, I can't do the same with afterEach().timeout(120000), because the function does not exist - nor can I use the function ()-notation due to the unknown resource names:
describe('Resources', function () {
beforeEach(() => {
this._resources = null
})
it('should create resources', async () => {
this._resources = await createResources()
expect(false).to.equal(true) // fail test, so...
await deleteResources() // will never be called
})
afterEach(async() => {
this._resources.map(entry => {
await // ... delete any created resources ...
})
}).timeout(120000)
})
Any hints? Mocha is version 4.0.1, chai is 4.1.2
The rules are same for all Mocha blocks.
timeout can be set for arrow functions in Mocha 1.x with:
afterEach((done) => {
// ...
done();
}).timeout(120000);
And for 2.x and higher it, beforeEach, etc. blocks are expected to be regular functions in order to reach spec context. If suite context (describe this) should be reached, it can be assigned to another variable:
describe('...', function () {
const suite = this;
before(function () {
// common suite timeout that doesn't really need to be placed inside before block
suite.timeout(60000);
});
...
afterEach(function (done) {
this.timeout(120000);
// ...
done();
});
});
Mocha contexts are expected to be used like that, since spec context is useful, and there are virtually no good reasons to access suite context inside specs.
And done parameter or promise return are necessary for asynchronous blocks.
If you need to use dynamic context you have to use normal function.
describe('Resources', function () {
// ...
afterEach(function (){
this.timeout(120000) // this should work
// ... delete any created resources ...
})
})

Javascript Mocha schedule one time test data cleanup

I am writing a mini-framework for executing unit tests for a product I work on. I want test data to be published and managed as seamlessly as possible. With Mocha, it is easy to schedule test data cleanup using the After() hook.
You could wrap an individual test in a describe() block and use that block's Before/After method, but that I'd rather avoid that if possible.
You could pass a cleanup function to afterEach which specifically targets data populated inside a test. Though that would only be necessary for one cleanup and it seems clunky to do that.
Is it possible to generate test data within one test, just for the sake of that test, and also schedule a cleanup for it with Mocha?
Sure, just run your generation and cleanup in the test itself. If it's asynchronous, you can use the done callback to make it wait until it's called.
mocha.setup('bdd');
describe('suite', function() {
function getData() {
// Simulate asynchronous data generation
console.log('grabbing data');
return new Promise((resolve, reject) => {
setTimeout(() => resolve(100), 500);
});
}
function cleanup() {
// Simulate asynchronous cleanup
console.log('cleaning up...');
return new Promise((resolve, reject) => {
setTimeout(resolve, 500);
});
}
it('should do generation and clean up', function(done) {
// Generate some data
getData()
.then(data => {
// Test the data
if (data !== 100) {
throw new Error('How?!');
}
console.log('test passed');
// Cleanup
return cleanup();
})
.then(_ => {
// Use done() after all asynchronous work completes
console.log('done cleaning');
done();
})
.catch(err => {
// Make sure it cleans up no matter what
cleanup().then(_ => console.error(err));
});
});
});
mocha.run();
<script src="https://cdn.rawgit.com/mochajs/mocha/2.2.5/mocha.js"></script>
<div id="mocha"></div>
I think cleanup after test is generally problematic because cleanup consistency guarantees aren't very strong, ie is cleanup function guaranteed to run? probably not. If it's not assured that cleanup will take place then it could very well leave the next tests in an inconsistent state. I think it's good to make an attempt but you can guard against failure by:
cleaning up/establishing db state BEFORE each test
nuking the world so each test has a consistent state (can be accomplished by executing your test in the context of a transaction and rolling back the transaction after each test, and at least not ever committing the transaction)
having test create unique data. By leveraging unique data you can also run your tests in parallel, since it allows for multiple different tests to have an isolated view of the db. If each test writes its own data you only have to worry about provisioning the whole db at the beginning of each test run
Of the above if you're able to wrap your test in a transaction it is lightning fast, (web frameworks like django and rails do this and it is quite fast and makes tests/db state very easy to reason about)

Categories

Resources