Jasmine-node tests always pass - node.js

I'm new to BDD and for some reason my code always seem to be passing although I haven't yet written any code. Can somebody please explain why this is happening?
Project setup:
I have a project folder with package.json and a test section with the following declared: ".node_modules/.bin/jasmine-node" and a folder called spec with the following code file:
var request = require("request");
describe("Web Server Test", function() {
it("GET /", function(done) {
request.get("http://localhost/", function(error, request, body) {
expect(body).toContain("Hello, World!");
});
done();
});
});
This is the output I get:
C:\Users\\OneDrive\Documents\Websites\Projects\Node\project>npm
test spec/app_spec.js
Project#0.0.0 test
C:\Users\\OneDrive\Documents\Websites\Projects\Node\project
jasmine-node "spec/app_spec.js"
.
Finished in 0.031 seconds 1 test, 0 assertions, 0 failures, 0 skipped

the done callback must be called inside request callback...
it("GET /", function(done) {
request.get("http://localhost/", function(error, request, body) {
expect(body).toContain("Hello, World!");
// THIS IS ASYNC
done();
});
});

Related

Log response body on mocha test errors?

When running mocha tests using npm run test, is it possible to have the contents of the response body printed whenever a test fails with an error?
chai.request(server)
.post('/')
.set('X-Access-Token', testUser.accessToken)
.send(fields)
.end((error, response) => {
console.log(response.body); // log this!
response.should.have.status(201); // if this fails!
done();
});
});
In other words, could the afterEach function have access to error and response for each test?
afterEach(function(error, response) {
if (error) console.log('afterEach', response.body);
});
We have useful error messages coming down in the response, so we find ourselves pasting that console.log line into the failing test to debug. It'd be nice to always see the response.body on each error.
OP here - I came up with an answer and figured I'd leave it here until someone comes up with a better one.
The reason it's not ideal is that it requires a single line in each test, which updates a shared variable currentResponse with that test's response. But if your tests span many files, you can maintain a global variable in your setup script:
// you can use a global variable if tests span many files
let currentResponse = null;
afterEach(function() {
const errorBody = currentResponse && currentResponse.body;
if (this.currentTest.state === 'failed' && errorBody) {
console.log(errorBody);
}
currentResponse = null;
});
And then each of your tests would update the current response, so we can log it in the afterEach, in the event that it fails.
describe('POST /interests', () => {
it('400s if categoryName field is not present in the category', done => {
const fields = [
{ language: 'en' },
];
chai.request(server)
.post('/interests')
.set('X-Access-Token', testUser.accessToken)
.send(fields)
.end((error, response) => {
currentResponse = response; // update it here
response.should.have.status(400);
done();
});
});
And this will output the response whenever there's an error, so you can see what the server returned.

Node-Jasmine not failing when expected

I'm trying to setup a node-jasmine test for the first time. Currently I'm just trying to setup a simple test to see that getting the index returns status 200.
It seemed to be working but I noticed no matter what I change the status number to it never fails, for example expecting status 666, but I don't get a failure:
const request = require("request")
const helloWorld = require("../app.js")
const base_url = "http://localhost:3002/"
describe("Return the index page", function() {
describe("GET /", function() {
it("returns status code 200", function() {
request.get(base_url, function(error, response, body) {
expect(response.statusCode).toBe(666)
done()
})
})
})
})
Which returns:
Finished in 0.009 seconds
1 test, 0 assertions, 0 failures, 0 skipped
When I expected a failure here.
You need to include the done callback as a parameter to the test function.
Eg:
it("returns status code 200", function(done) {
request.get(base_url, function(error, response, body) {
expect(response.statusCode).toBe(666)
done();
})
})
Without this, the test is completing before the asynchronous request returns.
While it looks like you found your answer, I came here with a similar problem. My problem was that the request was failing, and the assertion was never reached. Once I added an error catch like below, I found my problem!
I'm new to Jasmine, but it seems odd that an exception generated inside your test wouldn't be more visible or apparent, so if anyone has feedback on how to better handle, let me know.
const request = require("request")
const helloWorld = require("../app.js")
const base_url = "http://localhost:3002/"
describe("Return the index page", function() {
describe("GET /", function() {
it("returns status code 200", function() {
request.get(base_url, function(error, response, body) {
if (error)
console.log("Something borked: ", error);
expect(response.statusCode).toBe(666)
done()
})
})
})
})

How to mock seneca calls in Node.js using jasmine-node?

I am using express module and below is the code of app.js
app.post('/test_url', function(request, response){
seneca.client({type: 'http',port: '3000',host: 'localhost',protocol: 'http'}).act({role: 'sample_role', cmd: 'save',firstname: request.params.firstname}, function (err, result) {
console.log("Inside Seneca act");
response.json(result);
})
});
Below is the test file where I am writing the test case for above code.
describe("POST /test_url/:firstname", function() {
it("should return status code 200", function(done) {
<b>//here I want to mock the call for seneca.client so that I can test if the call has been made with the required parameters.</b>
<b>//Also I would like to use the above mock object to further mock the call for act so that I can check if the act method has been called with the required parameters.'</b>
//Main purpose behind doing so is that I do not want the seneca methods to get actually called, and only want to test if the call has been made.
request.post("http://localhost:3000/test_url/sara", function(error, response, body) {
//some verification method on the mock object so as to confirm that both the calls i.e 'seneca.client' and 'seneca.client().act' have been called with the appropriate parameters
expect(body).toContain("success");
done();
});
});
});
I tried to mock the seneca calls using jasmine spy and sinon but still the call was actually being going to the method and the the callback function was also invoked resulting in the console.log("Inside Seneca act"); being called, which is not what I expect.
describe("POST /test_url/:firstname", function() {
it("should return status code 200", function(done) {
var senecaCall = sinon.stub(seneca, 'client');
//or spyOn(seneca, "client");
request.post("http://localhost:3000/test_url/sara", function(error, response, body) {
expect(body).toContain("success");
done();
});
});
});

Mocha runs only one test

I have a sails.js app that I want to test with mocha, in my test folder I have 2 tests, but when I run mocha only one test gets executed.
Test1.js
var request = require('supertest');
describe.only('UserController', function() {
describe('#login()', function() {
it('should redirect to /mypage', function (done) {
done();
});
});
});
Test2.js
describe.only('UsersModel', function() {
describe('#find()', function() {
it('should check find function', function (done) {
done();
});
});
});
I run tests with this command:
./node_modules/.bin/mocha
Output
UserController
#login()
✓ should redirect to /mypage
1 passing (10ms)
Please explain me my mistake.
It is because you are running an exclusive test by using describe.only(). Use describe() instead.
See exclusive tests in the mocha documentation

In mocha testing while calling asynchronous function how to avoid the timeout Error: timeout of 2000ms exceeded

In my node application I'm using mocha to test my code. While calling many asynchronous functions using mocha, I'm getting timeout error (Error: timeout of 2000ms exceeded.). How can I resolve this?
var module = require('../lib/myModule');
var should = require('chai').should();
describe('Testing Module', function() {
it('Save Data', function(done) {
this.timeout(15000);
var data = {
a: 'aa',
b: 'bb'
};
module.save(data, function(err, res) {
should.not.exist(err);
done();
});
});
it('Get Data By Id', function(done) {
var id = "28ca9";
module.get(id, function(err, res) {
console.log(res);
should.not.exist(err);
done();
});
});
});
You can either set the timeout when running your test:
mocha --timeout 15000
Or you can set the timeout for each suite or each test programmatically:
describe('...', function(){
this.timeout(15000);
it('...', function(done){
this.timeout(15000);
setTimeout(done, 15000);
});
});
For more info see the docs.
I find that the "solution" of just increasing the timeouts obscures what's really going on here, which is either
Your code and/or network calls are way too slow (should be sub 100 ms for a good user experience)
The assertions (tests) are failing and something is swallowing the errors before Mocha is able to act on them.
You usually encounter #2 when Mocha doesn't receive assertion errors from a callback. This is caused by some other code swallowing the exception further up the stack. The right way of dealing with this is to fix the code and not swallow the error.
When external code swallows your errors
In case it's a library function that you are unable to modify, you need to catch the assertion error and pass it onto Mocha yourself. You do this by wrapping your assertion callback in a try/catch block and pass any exceptions to the done handler.
it('should not fail', function (done) { // Pass reference here!
i_swallow_errors(function (err, result) {
try { // boilerplate to be able to get the assert failures
assert.ok(true);
assert.equal(result, 'bar');
done();
} catch (error) {
done(error);
}
});
});
This boilerplate can of course be extracted into some utility function to make the test a little more pleasing to the eye:
it('should not fail', function (done) { // Pass reference here!
i_swallow_errors(handleError(done, function (err, result) {
assert.equal(result, 'bar');
}));
});
// reusable boilerplate to be able to get the assert failures
function handleError(done, fn) {
try {
fn();
done();
} catch (error) {
done(error);
}
}
Speeding up network tests
Other than that I suggest you pick up the advice on starting to use test stubs for network calls to make tests pass without having to rely on a functioning network. Using Mocha, Chai and Sinon the tests might look something like this
describe('api tests normally involving network calls', function() {
beforeEach: function () {
this.xhr = sinon.useFakeXMLHttpRequest();
var requests = this.requests = [];
this.xhr.onCreate = function (xhr) {
requests.push(xhr);
};
},
afterEach: function () {
this.xhr.restore();
}
it("should fetch comments from server", function () {
var callback = sinon.spy();
myLib.getCommentsFor("/some/article", callback);
assertEquals(1, this.requests.length);
this.requests[0].respond(200, { "Content-Type": "application/json" },
'[{ "id": 12, "comment": "Hey there" }]');
expect(callback.calledWith([{ id: 12, comment: "Hey there" }])).to.be.true;
});
});
See Sinon's nise docs for more info.
If you are using arrow functions:
it('should do something', async () => {
// do your testing
}).timeout(15000)
A little late but someone can use this in future...You can increase your test timeout by updating scripts in your package.json with the following:
"scripts": {
"test": "test --timeout 10000" //Adjust to a value you need
}
Run your tests using the command test
For me the problem was actually the describe function,
which when provided an arrow function, causes mocha to miss the
timeout, and behave not consistently. (Using ES6)
since no promise was rejected I was getting this error all the time for different tests that were failing inside the describe block
so this how it looks when not working properly:
describe('test', () => {
assert(...)
})
and this works using the anonymous function
describe('test', function() {
assert(...)
})
Hope it helps someone, my configuration for the above:
(nodejs: 8.4.0, npm: 5.3.0, mocha: 3.3.0)
My issue was not sending the response back, so it was hanging. If you are using express make sure that res.send(data), res.json(data) or whatever the api method you wanna use is executed for the route you are testing.
Make sure to resolve/reject the promises used in the test cases, be it spies or stubs make sure they resolve/reject.

Resources