Why can't I see console log output when testing node apps with jest - node.js

I am new to testing with jest and I cannot seem to be able to see the console output from modules I want to test.
my-module.js:
var _ = require('underscore');
exports.filter = function(data) {
if(_.isArray(data)) {
console.log("Data is: " + data);
data = data[0];
}
return data;
}
my-module-test.js:
jest.dontMock('../my-module');
var testdata = [{label: "test"}, {id: 5}];
describe('test my module', function(){
it('changes some data' , function(){
var transformedData = require('../my-module').filter(testdata);
expect(transformedData).toBe(testdata[0]);
});
});
Why is jest swallowing my console.log output in "my-module.js"?

Jest seems to mock everything by default. Which is the issue I encountered.
Underscore "_" was mocked and there was no visible error, so the execution never got to the console.log in the first place.
There are three possibilities (as far as I know) to prevent such a situation:
In your package.json file, prevent mocking of node modules (which includes underscore)
"jest": {
"unmockedModulePathPatterns": ["/node_modules/"]
}
Explicitly prevent auto mocking in your test file using:
jest.autoMockOff();
Explicitly exclude underscore from mocking:
jest.unmock('underscore');

Related

Does Rewire set the current running module variables as well as the specified module variables?

So, I was doing some testing with Rewire with Mocha, and I noticed behavior that seems odd to me. using myModule.__set__() seems to actually set the specified variable in the the specified module (myModule), AND in the global scope of the current module (the one that ran the __set__()). For example:
This code runs after running mocha test:
Test.js:
var rewire = require("rewire")
var sinon = require("sinon")
var test2 = rewire("./test2.js")
var expect = require("chai").expect
var spy = sinon.spy()
describe("test", function () {
beforeEach(function () {
test2.__set__("console", { log: spy })
})
it("test should be equal to 3", function () {
test2.test1()
console.log("testing5")
expect(spy.callCount).to.equal(3)
})
})
Test2.js:
module.exports = {
test1() {
console.log("test")
console.log("test")
console.log("test")
}
}
Here, I would expect "testing5" to actually be logged to the console, but the 3 "test"s to just be recorded in the spy, and the callCount to be equal to 3. This is not what is happening however. The "testing5" is not being logged, but is being recorded to that sinon spy, and the test is failing, because the callCount is 4, and not 3. To me this doesn't seem like this would be intended. Is there something I'm doing wrong?

Mocha (Spectron) suddenly times out on async test scenarios

I wanted to run some Spectron e2e tests I wrote some weeks ago, but to my surprise, suddenly they all stopped working for one and the same reason.
According to the error message, I'm dealing with rejected Promises, but I can't figure out where the problem is coming from. Calling done at the end of my testcase raises the exact same error.
I'm running the following command to launch my test suit: mocha test/e2e
Mocha then executes this index.js before running my tests in ordner to support ES6+ features
'use strict'
//index.js
// Set BABEL_ENV to use proper env config
process.env.BABEL_ENV = 'test'
// Enable use of ES6+ on required files
require('babel-register')({
ignore: /node_modules/
})
// Attach Chai APIs to global scope
const { expect, should, assert } = require('chai')
global.expect = expect
global.should = should
global.assert = assert
// Require all JS files in `./specs` for Mocha to consume
require('require-dir')('./specs')
After that its trying to run this small Login.spec.js which returns the error mentioned above
import utils from '../utils'
import {Application} from "spectron";
import electron from "electron";
describe('🔑 Login', function () {
this.timeout(11000);
it('login form exists', async function (done) {
this.app = new Application({
path: electron,
env: {"SPECTRON_RUNNING":true},
args: ['dist/electron/main.js'],
startTimeout: 10000,
waitTimeout: 10000
})
await this.app.start()
await this.app.client.windowByIndex(1);
done();
})
})

Unit test for node js

I am new to nodejs, and need to write unit test for a node project. I try to learn mocha and there are two questions:
when I write unit test for function A, in A it also use function B, so how can I mock an output for B?
how can I unit test these endpoints in app.js. like app.get, app.put.
can someone give me some suggestions or simple examples?
Can someone also give me some advice on writing unit test for nodejs, thanks so much.
Thanks so much everyone.
Answering Q1,
If the output of b method is used in a metheod, then you can make the test of b method first.
Otherwise you can prepare result of b in before section of your test method and use it in a method.
It depends on your approach of testing.
Answering Q2 -
You can use superagent for sending get or post request ...
Some code examples ...
require('should');
var assert = require("assert");
var request = require('superagent');
var expect = require('expect.js');
then,
describe('yourapp', function(){
before(function(){
// function start
start your server code
// function end
})
describe('server', function(){
describe('some-description', function(){
it('should return json in response', function(done){
request.post('http path')
.send(JSON.parse("your json"))
.end(function(res){
expect(res).to.exist;
expect(res.status).to.equal(200);
expect(res.text).to.contain('ok');
done();
});
})
});
})
after(function(){
//stop your server
})
});
Here done is an important aspect in a unit testing component for asynchronous method testing.
Some reference -
superagent
this blog post
Hope this will help you,
Thanks
Answering Q1,
If the funcitons in different modules,
You can use a mock tool : fremock
Using freemock You can do this:
your code
//function a exports in the module named mA
function a(){
return "1";
}
//function a exports in the module named mB
function b(){
a();
}
test code
var freemock = require('freemock');
freemock.start()
var mock_b = freemock.getMock('mB');
mock_b.setMethod({
"a":{
willReturn:"1"
}
})
freemock.end();
Some advice:
Mocha is good test framework for node.js .
For example,
Assert tool: should.js
Code coverage tool:istanbul
...
Mocha combines all this tools;
Here is a demo using Mocha:
your code(filename:mA.js)
//in the module named mA
function a(){
return true;
}
test code(filename:testmA.js)
var should = require('should');
beforeEach(function(){
//do something before testing
});
afterEach(function(){
//do something after testing
});
describe("test",function(){
describe("test1",function(){
it("if true",function(){
var mA = require('./mA');
var result = mA.a();
should.ok(result);
});
it("if false",function(){
//other test
});
});
describe("test2",function(){
it("test2-1",function(){
//other test
})
})
})
We should need run.js to start the test:
//run.js
var Mocha = require('mocha');
var mocha = new Mocha;
mocha.addFile(__dirname+'/test/testmA.js')
mocha.run();
The project dir tree is:
|- run.js
|
|- mA.js
|
|- test - testMA.js
Finally
Run this command:
istanbul cover run.js
Hope you enjoy!
I am recently involved in a node project where I have to run unit tests.
Eventually I wrote a small script runner for karma using NW.JS
This allowed me to access all node modules and run my tests on the server itself. I uploaded this project to github, Narma.
Right now it was only tested on a Mac

In mocha testing framework is there any possibility to store the test reports in local file

Im using mocha framework in my node application.If i run my test file using mocha means i'm getting error reports in terminal but i want to store the reports in local file.How can i do that.Is there any builtin method for this in mocha.
describe('Test with mocha', function(){
it ('result should be true',function(done){
var finalResult=false;
expect(finalResult).to.be(true);
done();
});
});
no there no built-in feature for mocha to do this, but you can do some other stuff by working with pipes which are standard in OSes.
open up a terminal, and give the command
mocha TEST.js > report.txt
the command above simply pipes all output to report.txt file.
You can also try working with child_process module from node, where you pretty much do the same thing as the command line, but in pure js.
*code is from node.js docs
var fs = require('fs'),
spawn = require('child_process').spawn,
out = fs.openSync('./out.log', 'a'),
err = fs.openSync('./out.log', 'a');
var child = spawn('prg', [], {
stdio: [ 'ignore', out, err ]
});
child.unref();
Ideally you can use mocha-junit-reporter and write output to XML file.
mocha tests --recursive --reporter mocha-junit-reporter --reporter-options mochaFile=./myJUnitfile.xml
If by local file you mean simple txt file then I have a sample code for you on which you can extend your own implementation. Please note that following code is only for knowledge sake. It doesn't handle many of the reporter events such as test suite start, and end etc., and exceptions that may be thrown by file operations.
For complete list of reporter events refer to https://github.com/mochajs/mocha/wiki/Third-party-reporters.
Also the following code is extended from the sample code present in above link.
// This code is extended on the orginal source present
// at https://github.com/mochajs/mocha/wiki/Third-party-reporters
// my-file-reporter.js
const mocha = require('mocha');
const fs = require('fs');
const os = require("os");
module.exports = MyFileReporter;
function MyFileReporter(runner, options) {
this._mochaFile = options.reporterOptions.mochaFile || process.env.MOCHA_FILE || 'test-results.txt';
mocha.reporters.Base.call(this, runner);
var passes = 0;
var failures = 0;
runner.on('start', function() {
if (fs.existsSync(this._mochaFile)) {
console.log('Removing existing test result file!');
fs.unlinkSync(this._mochaFile);
}
}.bind(this));
runner.on('pass', function(test){
passes++;
console.log('Pass: %s', test.fullTitle()); // Remove console.log statements if you dont need it (also below in code)
fs.appendFileSync(this._mochaFile, 'Pass: ' + test.fullTitle() + os.EOL); // Note: Exception not handled
}.bind(this));
runner.on('fail', function(test, err){
failures++;
console.log('Fail: %s -- error: %s', test.fullTitle(), err.message);
fs.appendFileSync(this._mochaFile, 'Fail: ' + test.fullTitle() + 'Error: ' + err.message + os.EOL); // Note: Exception not handled
}.bind(this));
runner.on('end', function(){
console.log('Test Summary: %d/%d', passes, passes + failures);
fs.appendFileSync(this._mochaFile, os.EOL + 'Test Summary: ' + passes + '/' + (passes + failures) + os.EOL); // Note: Exception not handled
}.bind(this));
}
Use the following command line (it assumes that my-file-reporter.js is present in the same folder where this command is executed)
mocha tests --recursive --reporter my-file-reporter --reporter-options mochaFile=./myfile.txt

Mocha and ZombieJS

I'm starting a nodejs project and would like to do BDD with Mocha and Zombiejs. Unfortunately I'm new to just about every buzzword in that sentence. I can get Mocha and Zombiejs running tests fine, but I can't seem to integrate the two - is it possible to use Mocha to run Zombiejs tests, and if so, how would that look?
Just looking for "hello world" to get me started, but a tutorial/example would be even better.
Thanks!
Assuming you already have installed mocha, zombie and expect.js according to instructions, this should work for you:
// Put below in a file in your *test* folder, ie: test/sampletest.js:
var expect = require('expect.js'),
Browser = require('zombie'),
browser = new Browser();
describe('Loads pages', function(){
it('Google.com', function(done){
browser.visit("http://www.google.com", function () {
expect(browser.text("title")).to.equal('Google');
done();
});
});
});
Then you should be able to run the mocha command from your root application folder:
# mocha -R spec
Loads pages
✓ Google.com (873ms)
✔ 1 tests complete (876ms)
Note: If your tests keep failing due to timeouts, it helps to increase mocha's timeout setting a bit by using the -t argument. Check out mocha's documentation for complete details.
I wrote a lengthy reply to this question explaining important gotchas about asynchronous tests, good practices ('before()', 'after()', TDD, ...), and illustrated by a real world example.
http://redotheweb.com/2013/01/15/functional-testing-for-nodejs-using-mocha-and-zombie-js.html
if you want to use cucumber-js for your acceptance tests and mocha for your "unit" tests for a page, you can use cuked-zombie (sorry for the advertising).
Install it like described in the readme on github, but place your world config in a file called world-config.js
`/* globals __dirname */
var os = require('os');
var path = require('path');
module.exports = {
cli: null,
domain: 'addorange-macbook': 'my-testing-domain.com',
debug: false
};
Then use mocha with zombie in your unit tests like this:
var chai = require('chai'), expect = chai.expect;
var cukedZombie = require('cuked-zombie');
describe('Apopintments', function() {
describe('ArrangeFormModel', function() {
before(function(done) { // execute once
var that = this;
cukedZombie.infectWorld(this, require('../world-config'));
this.world = new this.World(done);
// this inherits the whole world api to your test
_.merge(this, this.world);
});
describe("display", function() {
before(function(done) { // executed once before all tests are run in the discribe display block
var test = this;
this.browser.authenticate().basic('maxmustermann', 'Ux394Ki');
this.visitPage('/someurl', function() {
test.helper = function() {
};
done();
});
});
it("something on the /someurl page is returned", function() {
expect(this.browser.html()).not.to.be.empty;
});

Resources