Unit testing for loopback model - node.js

I have a Loopback API with a model Student.
How do I write unit tests for the node API methods of the Student model without calling the REST API? I can't find any documentation or examples for testing the model through node API itself.
Can anyone please help?

Example with testing the count method
// With this test file located in ./test/thistest.js
var app = require('../server');
describe('Student node api', function(){
it('counts initially 0 student', function(cb){
app.models.Student.count({}, function(err, count){
assert.deepEqual(count, 0);
});
});
});
This way you can test the node API, without calling the REST API.
However, for built-in methods, this stuff is already tested by strongloop so should pretty useless to test the node API. But for remote (=custom) methods it can still be interesting.
EDIT:
The reason why this way of doing things is not explicited is because ultimately, you will need to test your complete REST API to ensure that not only the node API works as expected, but also that ACLs are properly configured, return codes, etc. So in the end, you end up writing 2 different tests for the same thing, which is a waste of time. (Unless you like to write tests :)

Related

how to run test in certain cases?

I'm new to TDD and I wrote a few test functions that check the sign up and deletion of the user , but before each running i go to the database and delete the user before testing the sign up and i go to the database to put a dummy user info before deletion so my question is how does this thing run in actual production environment , like every time I want to run the tests , I go to the database and make all these modification , what if user signed up with the below credentials then the test would return 200 ?? (i use jest with nodejs e2e)
describe("given user is not found", () => {
it("should return 404", async () => {
await request(app)
.post("/api/v1/auth/signIn")
.send({
email: "s#gmail.com",
password: "s",
})
.expect(404);
});
});```
Other opinions are available but here's what I'd do.
Let's assume your backend is in java. Before I wrote any code I would have a test that called the API endpoint with the same input and expected a 404.
Some will tell you to mock the database with a library like Mockito but I don't think that's necessary. For our purposes a database is nothing but a map. A map takes an id and returns an object. So make an interface that describes interactions with your database, saveUser(), loadUser() - that kind of thing. Implement the interface with your real implementation. And implement it with your test one which is just a class with those same methods and a map for actually doing real work. This is called a fake.
Your api could return a 404 if the user is not found or a 200 if it is. Your test is in the backend and its quicker than it was before because you're not hitting a real database.
As far as your example goes I really don't think you need to set anything up in the database at all. But if you absolutely must then you could have an endpoint which tears down the database setup and sets it up again, which is executed at the start of the test. Or a database image that you stand up just for the test. Both are probably overkill.

Node.JS: Refreshing the nodemailer-mock after each test in Jest

I am building a Node JS application using Express.js framework. My application is sending email using the nodemailer package, https://nodemailer.com/about/. I am writing test using supertest and Jest. I am using nodemailer-mock package, https://www.npmjs.com/package/nodemailer-mock to mock my application.
I can mock the logic for sending email for Jest as mentioned in the nodemailer-mock documentation. The only issue is that it is not resetting the data/ count after each test. For example, I have two tests and both are sending emails and when I do the following assertion, it is failing.
const sentEmails = mock.getSentMail();
// there should be one
expect(sentEmails.length).toBe(1);
It is failing because an email was sent in the previous test. How can I reset it?
Assuming your mock variable is set (or even imported) at the module level, this should cover it:
afterEach(() => {
mock.reset();
});
Keep in mind that this method also seems to reset anything else you have configured on the mock (success response, fail response, etc.), so you may need to perform that setup each time too. That would be a good fit for a beforeEach block.

Adding a default before() function for all the test cases (Mocha)

I'm writing functions for my node.js server using TDD(Mocha). For connecting to the database I'm doing
before(function(done){
db.connect(function(){
done();
});
});
and I'm running the test cases using make test and have configured my makefile to run all the js files in that particular folder using mocha *.js
But for each js file I'll have to make a separate connection to the database, otherwise my test cases fail since they do not share common scope with other test files.
So the question is, Is there anything like beforeAll() that would just simply connect once to the database and then run all the test cases? Any help/suggestion appreciated.
You can setup your db connection as a module that each of the Mocha test modules imports.
var db = require('./db');
A good database interface will queue commands you send to it before it has finished connecting. You can use that to your advantage here.
In your before call, simply do something that amounts to a no op. In SQL that would be something simple like a raw query of SELECT 1. You don't care about the result. The return of the query just signifies that the database is ready.
Since each Mocha module uses the same database module, it'll only connect once.
Use this in each of your test modules:
before(function(done) {
db.no_op(done);
});
Then define db.no_op to be a function that performs the no op and takes a callback function.

Test environment in Node.js / Express application

I've just starting working with Node, and I've been following along with various tutorials.
I've created an Express app, and setup Mongoose and Jasmine.
How can I configure my specs so that I can:
create models, automatically clean them up after each spec
use a different database for creating test objects (say myapp_test)
do this in a way that is as DRY as possible, i.e. not creating a before / after block with the teardown for each describe block
?
I'll try to answer you.
Create models, automatically clean them up after each spec.
To do that I'll assume you use Mocha as the testing framework you can simply use the function beforeEach like this :
describe('POST /api/users', function() {
beforeEach(function(done) {
User.remove({}, function (err) {
if (err) throw err;
done();
});
});
});
Basicly what I'm doing here is cleanning up my database before each it but you can make it do anything you want.
Use a different database for creating test objects
Here, you should use the node process.env method to setting your env. Here is a article to understand a little how it works. Take a lot to GRUNT projects, it helps a lot with your workflow and the configurations stuff.
do this in a way that is as DRY as possible, i.e. not creating a
before / after block with the teardown for each describe block
I'm not sure I got what you want but take a look at the doc for the hooks before, after, beforeEach, afterEach. I think you will find what you want here.

How do I unit test keystonejs models?

Is there any way to run tests for keystonejs that also hit a test or real mongodb instance?
It would be nice if similar to the way Django does it.
There aren't any official examples of implementing unit testing for KeystoneJS sites yet, but there wouldn't be anything stopping you from writing tests with a framework like mocha, the way you would in any other node.js app.
You'd want to initialise Keystone, register your models, then connect to the database and execute tests without starting the web server. Something like this:
./tests.js
var keystone = require('keystone');
keystone.init({
'name': 'Your Project'
});
keystone.import('models');
keystone.mongoose.connect('localhost', 'your-database');
keystone.mongoose.connection.on('open', function() {
// Run tests here
// Use keystone.list('Key') to access Lists and execute queries
// as you would in your main application
});
then run tests.js, or make it an npm / grunt / etc. script.
Keep an eye on issue #216 for an integrated testing framework.

Resources