How to reset the loopback memory DB - node.js

I am running several loopback tests via mocha (let's call them test1.js, test2.js and test3.js).
When i run the independently everything works well. However, when I ask mocha to run them all, things that are created in the first test in the in-memory DB collide with tests being done later on (test 2 or 3).
Is there a way to ensure we start each test with an empty DB? Something like:
app.dataSources.db.reset()
Thanks a lot!
UPDATE: What I ended up doing: I looked at the DataSource code and found that you can do automigrate on the memory DB.
before("wipe DB (if used with other tests)", function(done) {
app.dataSources.db.automigrate(function(err) {
done(err);
});
});

Get a hold of the db via app.dataSources.db and execute automigrate as in:
before("wipe DB (if used with other tests)", function(done) {
app.dataSources.db.automigrate(function(err) {
done(err);
});
});
Cheers.

Normally you should clean up after each test.
You can use hooks, like afterEach

Related

Is there any way to add callbacks to Jest when all tests succeed or fail?

I'd like to run a callback when all the tests in a describe block pass (or fail), is there some hook or something in the Jest API to do this? I could not find anything applicable in the docs.
I'm making several API requests to collect data in order to compare it to data in a CSV file, in order to diff the contents. When the tests have all passed, I would like to save all the API responses in a file, therefore I need some sort of 'all tests passed' callback
You can run jest programmatically. Note that this approach is "hack" because there is no official support for running jest like this.
see: https://medium.com/web-developers-path/how-to-run-jest-programmatically-in-node-js-jest-javascript-api-492a8bc250de
There is afterAll that is aware of describe but runs regardless of test results. It can be used as a part of function to aggregate data from tests:
let responses;
testAndSaveResponses((name, fn) => {
if (!responses) {
responses = [];
} else {
afterAll(async () => {
if (!responses.includes(null)) {
// no errors, proceed with response processing
}
});
}
test(name, async () => {
try {
responses.push(await fn());
} catch (err) {
responses.push(null);
throw err;
}
});
});
It's supposed to be used instead of Jest test and be enhanced to support multiple describe scopes.
There is custom environment. Circus runner allows to hook test events, finish_describe_definition in particular. It is applied to all tests, unaware of custom data (e.g. responses that need to be saved) and should interact with them through global variables.
There is custom reporter, it receives a list of passed and failed tests. It is applied to all tests, unaware of custom data defined in tests and doesn't have access to globals from test scope so cannot be used to collect responses.

Testing Involving Database

well before specifying my problem, i want to tell that i'm new to the field of testing, so here is my problem:
i developed a rest api using express + sequelize(mysql), and i want to write some test for my api. i choosed to use jasmine library for testing.
so right know i want to test the create and update rest endpoint, i will need access to a database, but the problem is that the test cases are run in parallel, and there is only one database, so if i want to delete all item from a table in a test case, and another test case have create a row in that table, there will be a problem.
const request = require('superagent');
const models = require('../../src/models');
const Station = models.Station;
describe("station testing", function () {
before(() => {
// delete and recreate all database table
// before running any test
});
describe("crud station", function () {
it('should create model', () => {
Station.create({
'name': 'test',
lat: 12,
long: 123,
}).then( model => {
expect(model).toBeTruthy();
});
});
it('should delete evrything', () => {
Station.deleteAll().then( () => {
// problem here if after the first model is created and before create model except is executed
expect(Station.Count()).toEqual(0);
}
});
});
});
Your problem is that you are not writing unit tests here.
You need to understand the most important rule of unit testing - only test one unit at a time. A unit can be thought of as an area of your code. In a traditional desktop project (Java, C#, etc), a unit would be one class. In the case of Javascript, a unit is harder to define, but it certainly will only include the Javacript. If you are including any server code (for example, the database) in your tests, then you are not unit testing, you are doing integration testing (which is also very important, but much harder).
Your Javascript will have dependencies (ie other code that it calls, say via Ajax calls), which in your case will include the server code that is called. In order to unit test, you need to make sure that you are only testing the Javascript, which means that when running the tests, you don't want the server code to be called at all. That way, you isolate any errors in that unit of code, and can be confident that any problems found are indeed in that unit. If you include other units, then it could be the other units that have the problem.
In a strongly-typed language (like Java, C#, etc), there are frameworks that allow you to set up a mock for each dependency. Whilst I haven't tried any myself (that's this week's job), there are mocking frameworks for Javascript, and you would probably need to use one of them to do real unit testing. You mock out the server code, so when you run the test, it doesn't actually hit the database at all. Apart from solving your problem, it avoids a whole load of other issues that you will likely hit at some point with your current approach.
If you don't want to use a mocking framework, one other way to do it is to change your Javascript so that the function you are testing takes an extra parameter, which is a function that does the actual server call. So, instead of...
deleteCustomer(42);
deleteCustomer(id) {
validate(id);
$.ajax(...);
}
...your code would look like this...
deleteCustomer(42, callServer);
deleteCustomer(id, serverCall) {
validate(id);
serverCall(id);
}
...where serverCall() contains the Ajax call.
Then, to unit test, you would test something like this...
deleteCustomer(42, function(){});
...so that instead of calling the server, nothing is actually done.
This is obviously going to require some rewriting of your code, which could be avoided by mocking, but would work. My advice would be to spend some time learning how to use a mocking framework. It will pay off in the long run.
Sorry this has been a bit long. Unfortunately, you're getting into a complex area of unit testing, and it's important to understand what you're doing. I strongly recommend you read up about unit testing before you go any further, as a good understanding of the basics will save you a lot of trouble later on. Anything by Robert Martin (aka Uncle Bob) on the subject will be good, but there are plenty of resources around the web.
Hope this helps. If you want any more info, or clarification, ask away.
Jasmine supports a function for beforeEach which run before each spec in a describe block.
You can use that.
describe("A spec using beforeEach and afterEach", function() {
var foo = 0;
beforeEach(function() { foo += 1; });
afterEach(function() { foo = 0; });
it("is just a function, so it can contain any code", function() {
expect(foo).toEqual(1);
});
it("can have more than one expectation", function() {
expect(foo).toEqual(1)
expect(true).toEqual(true);
});
});
So you could let the beforeEach take care of the delete operation.

How to run 'After' code on Mocha only on specific tests?

Edit: This question was answered, but I have another, similar question which I didn't want to open a new thread for.
I'm using Mocha and Chai to test my project.
As part of my code, I create a new user and save him in our DB (so the test user can perform various methods on our app).
Generally, after every test I would like to run a code block that deletes the user from the DB, which I did using the "AfterEach" hook.
My problem is that I have 1 test (might be more in the future) which doesn't create a user (e.g, 'try to login without signing up'), so my AfterEach code receives an error (can't delete something that doesn't exist).
Does Mocha supply a way to disable the 'AfterEach' on some tests? Or some other solution to my problem.
Edit: Added question: my AfterEach hook involves an async method which returns a promise. On the Mocha documentation I only saw an example for async hooks that work with callbacks. How am I supposed to use an afterEach hook that returns a promise
You can nest describe blocks, so you can group user interaction tests and also group the "with user" and "without user" tests:
describe('user interaction', () => {
describe('with user in database', () => {
// these will run only for the tests in this `describe` block:
beforeEach(() => createUser(...));
afterEach (() => deleteUser(...));
it(...);
});
describe('without user in database', () => {
it(...);
});
});

Simulating Failure to Access Mongodb

I create an Express.js library that uses the official Node.js driver for its Mongodb operations.
I'm currently in the process of writing unit tests and I want to simulate failures to access the database in order to ensure:
The library acknowledges failure cases (handles the error)
Makes the right error callbacks and fires the proper events.
I want the tests to run cross-platform, preferably without having to shut down or start the database with special parameters.
Looking at the reference for commands, the sleep command seems to do almost exactly what I want, but the waiting time in seconds in pretty long, plus it is flagged as for internal use only and you need to fire the database with a special parameter for it to work. The forceerror command looks like another good one, but again, it's listed for internal use only and the description is vague to say the least.
I am wondering if there is any recommended (preferably not overly hackish) way of doing this.
Here, it requires superuser privileges for the node process executing this script to send signals to the MongoDB process without having spawned it, but it is the best I found so far to simulate unresponsiveness:
var MongoDB = require('mongodb');
MongoDB.MongoClient.connect("mongodb://localhost:27017/SomeDB", {'server': {'socketOptions': {'connectTimeoutMS': 50, 'socketTimeoutMS': 50}}}, function(Err, DB) {
if(Err)
{
console.log(Err);
}
else
{
DB.command({'serverStatus': 1}, function(Err, Result) {
if(Err)
{
console.log(Err)
}
else
{
process.kill(Result.pid, 'SIGSTOP');
//Put testing logic to test unresponsiveness
process.kill(Result.pid, 'SIGCONT');
DB.close();
}
});
}
});
Edit:
If your testing logic crashes on Linux, you can resume the MongoDB process manually on the shell by executing:
kill -CONT PID
Where PID is the process id of the MongoDB process.

How do you instruct mocha/nodejs to wait till all db operations are over

I'm trying to test if some of my db operations are executed properly. The flow is as follows (I'm using mocha for testing)
Call code which loops through data and saves it to redis
Get data from redis (in my testcase) to see if it saves the right data.
I'm noticing that the get data from db gets executed much before anything is saved. I was looking at the done() option in mocha, however that seems to work only if data is saved through mocha (setup etc).
So how do I instruct mocha to wait for all db to be saved before trying to retrieve from db?
Thanks for any help
dankohn is correct. Here's what you need to do, a bit more fleshed out:
describe('Your test', function () {
before(function (done) {
Your.redis.db.call.here(your, parameters, function (err) {
...you may want to check for errors first...
done();
});
});
it('should do what you wanted...', function (done) {
...your test case...
done();
});
});
Your redis call most likely provides a callback function as a parameter. That callback function is executed when the redis call is completed. Within that callback function, call done(). The data you wrote will be there throughout your tests.
You just need to write a before function with the parameter done in mocha to load the data into the database. As a callback for when your data is loaded, call done(). Now, all your data will load before your first test.

Resources