How do I get everything covered? - javascript

I have a node module I'm trying to write unit tests for. Here's a part of the module:
function _write(level, message) {
if (level <= _current) {
message = message || "No message provided.";
const consoleFn = consoleFunction[level];
const logFn = console[consoleFn];
logFn(`${levelPrefix[level]}: ${message}`);
}
}
When I run the tests including this one:
test('test writing to error log', () => {
logger.__Rewire__('_write', function (level, message) {
console.error(`ERROR: ${message}`);
});
const spy = jest.spyOn(logger, 'error');
logger.error('error message');
expect(spy).toHaveBeenCalledTimes(1);
});
However after running the tests it still looks like the _write function isn't showing up in the coverage results. Is there a way to get jest to understand all the lines of code are getting exercised? Note that "Uncovered Line #s" refers to the exact line numbers of the _write function. I had hoped that by rewiring the function this would make my coverage 100%.

It looks to me like you are mocking the _write function for that test. I don’t expect those lines to get run in this case.
You could write another test that actually uses the _write function.

Related

Externally determine which test cases fail - Javascript

I am working on an problem for which i need to detect which test cases fail for any javascript/node.js application, when that application's test suite is run. I need to determine this in a programmatic manner.
Mocha testsuite output result
Consider an example of test output above, for this example I would like to write an external javascript script that can tell me which particular test case failed.
Currently the only solution in my mind is; executing npm test in a javascript child process and read its output from the stdout stream, parse the output and extract necessary information, something like this.
const { spawn } = require('child_process');
const chalk = require('chalk');
const child = spawn('npm.cmd',['test']);
line = 0
child.stdout.on('data', (data) => {
console.log(`${chalk.bgBlue('line = ' + line)} , data = ${data}`);
line++;
});
However, this would be a very strict approach. I would like a more generic way of going about it, that can work for a variety of test modules(not just mocha).
Help would be appreciated !
You can get the state for every test after the execution into the code. So you can know if the test has been passed or not.
The code you need is quite simple. Something like this:
afterEach(function () {
const state = this.currentTest.state;
if (state !== "passed") {
//Do whatever you want with this value
}
});
For example, if you want to store into code, which test has been failed, then you can code this:
var testFailed = []
describe('test', function () {
afterEach(function () {
const state = this.currentTest.state;
if (state !== "passed") {
testFailed.push(this.currentTest.title)
}
});
after(function(){
console.log(testFailed)
})
it('test1', () => {
assert.equal(1, 1)
});
it('test2', () => {
assert.equal(1, 2)
});
})
And the output will be:
test
√ test1
1) test2
[ 'test2' ]
1 passing (15ms)
1 failing
Now you can play with this. You can use the variable to do your work, or even you can create a file or whatever you want to store the info.

Testing the Observer complete event with Jest?

The RxJS Observer fires the events:
complete
error
next
If we want to test for the complete event with Jest. How is this done?
For example we can test the next and error events, because those functions pass data:
o.subscribe(result => {
expect(result.data.length).toEqual(1);
},
(e)=>{expect(e).toBeFalsy()},
()=>{ WHAT TO EXPECT HERE? }
The complete event does not. The function signature is ()=>void. How do we test that function signature?
Also the line (e)=>{expect(e).toBeFalsy()} because it never actually fires. Is there a way to check that a callback does not run?
const toPromise = obs =>
new Promise((complete, error) => {
obs.subscribe({ complete, error });
});
import { getUserEvents } as user from '../user';
// The assertion for a promise must be returned.
it('works with promises', () =>
expect(toPromise(getUserEvents(4))).resolves.toEqual('Mark'))
Via:
https://jestjs.io/docs/en/tutorial-async
https://github.com/ReactiveX/rxjs/issues/3482#issuecomment-385106653
Furthermore, since Jest will fail on Errors being thrown, you can use any testing framework inside of its test. E.g. import 'rxjs/testing', like described here
How to test that the error callback is not called is here.
Looks like this will test the complete callback:
let complete = false;
let completeHandler = ()=>{
complete = true;
expect(complete).toBeTruthy()
};
let errorHandler = (e)=>{
console.log("THIS IS NEVER EXECUTED");
console.log("HOW DO WE VERIFY THAT IT IS NOT?");
let o:Observable<Result> = fn(data, errorHandler, completeHandler);
o.subscribe();
The errorHandler and completeHandler are baked into the Observable<Result returned by the fn function.

Can I hide failure details in mocha output?

Sometimes when running a set of mocha tests I don't care about failure details; I only want a list of tests with pass or fail. I've tried several reporters, but they all seem to output details for failures. I like the default spec reporter structure, but I can't find how to hide the details.
Here's an illustrative example. For these tests:
const assert = require('assert')
describe('test test', function() {
it('should pass', function() {
})
it('should fail', function() {
assert(false)
})
})
Which gives output like this:
test test
✓ should pass
1) should fail
1 passing (9ms)
1 failing
1) test test
should fail:
AssertionError [ERR_ASSERTION]: false == true
+ expected - actual
-false
+true
at Context.<anonymous> (test-solution.js:69:5)
but what I want is just this:
test test
✓ should pass
1) should fail
1 passing (9ms)
1 failing
Am I missing something obvious, or are these details just not something I can suppress?
I wanted to hide this too and for me it seems also that most default reporters are not so nice. Each line that is useless will cost us time. In my eyes it should be very simple to customize the output.
Building a own custom reporter is the correct answer to your question. However - as this took me to long - here a very short and easy alternative: Disable the reporter and do some logs on the events.
const Mocha = require('mocha');
let file = './devtest.js';
let passCount = 0;
let errors = [];
// start with disabled reporter
const mocha = new Mocha({ reporter: function () {} });
mocha.addFile(file);
console.log('\n===== start mocha file ' + file);
mocha.run()
.on('pass', function (test) {
passCount++;
logSuccess(test.title);
})
.on('fail', function (test, err) {
errors.push({test, err});
logError(test.title);
})
.on('end', function () {
console.log();
console.log(' -------------------------');
logSuccess(passCount + ' tests passed');
logError(errors.length + ' tests failed');
// do something here - like:
// callback(errors)
});
function logSuccess (str) {
console.log('\u001b[32m ✓ \u001b[0m\u001b[90m' + str + '\u001b[0m');
}
function logError (str) {
console.log('\u001b[31m ✖ ' + str + '\u001b[0m');
}
Of course this has some features less compared to the standard reporter, but extending is pretty simple - you have all the errors and data. So it is very fast.
Perhaps anybody else can post a very simple working example a custom reporter for that - for me the custom reporter broke my console output and I was not interested in more debugging.

Mocha Unit Test Error Handling from Library

I have the following code below that basically gets a user from a database. The code below is using Dynamoose but I'm assuming there is something similar in many other libraries and packages.
User.get(searchid, function(err, user) {
if (err) {
console.log(err);
return res.send('error');
} else {
//DO LOGIC
}
});
I have written unit tests to handle all the logic inside the else statement above. But I'm trying to figure out if there is a way to write unit tests to handle the if (err) section of the code. Basically I want to write unit tests to make sure that if there is an error it returns the correct stuff tho I would be up for any suggestions of other tests I should write. How can I write tests in this case and cover this code with unit tests?
You should mock User.get to make it execute the callback directly, with the parameters you want.
To do that, you may have multiple possibility depending on your test setup.
I use rewire https://github.com/jhnns/rewire
If your code look like :
//myCode.js
var User = require('./model/User');
module.exports = function(){
User.get(searchid, function(err, user) {
if (err) {
console.log(err);
return res.send('error');
} else {
//DO LOGIC
}
});
}
Basicaly your test look like :
var myCode = rewire("../lib/myCode.js");
...
var UserMock = {
get: function (searchid, cb) {
cb(new Error(), null);
}
};
myCode.__set__("User", UserMock);
myCode.myFunctionCallingUserGet(function (err, data) {
// Test that you send error.
});

Run async code from command line, node js

I have a function that generates some test data and inserts it to a mongodb:
'use strict';
const CvFaker = require('./cv-faker');
const mongoose = require('mongoose');
require('../models/cv_model.js');
module.exports.init = function(){
var cvfaker = new CvFaker();
cvfaker.genCvs(100);
mongoose.model('cv').create(cvfaker.cvs, (err, createdCvs) => {
if(err){
console.log('something went wrong');
}
})
};
I want to execute this code from the command line:
node -e 'require("./create-mock-db").init()'
The function executes, but it does not wait for the function to complete since it is async. How do I make it wait for the function to complete?
This is not working either:
module.exports.init = function(cb){ ...
..
cb();
node -e 'require("./create-mock-db").init(function(){})'
As this answer might come up for more people…
// test.js
const request = require('request');
const rp = require('request-promise');
const demo = module.exports.demo = async function() {
try {
const res = await rp.post( {
uri: 'https://httpbin.org/anything',
body: { hi: 'there', },
}, function (error, response, body) {
return error ? error : body;
} )
console.log( res )
return res;
}
catch ( e ) {
console.error( e );
}
};
Call it like this:
$ node -e 'require("./test").demo()'
Sidenote:
it does not wait for the function to complete since it is async
It's not async. You might call asynchronous functions, but you are not treating them as such and not awaiting any result.
The node process will not exit until the event queue is empty. The event loop uses the event queue to make asynchronous execution possible.
It's pretty simple to verify that this is not an issue with executing asynchronous code.
node -e "setTimeout(() => console.log('done'), 5000)"
This example takes 5 seconds to run, as you would expect.
The problem with your code is the fact that you never establish a connection with the database. The model.create method doesn't do anything until there is a connection, therefor nothing ever gets queued and the process is free to exit.
This means your code needs to change to do two things:
Connect to the database so that the model.create method can execute.
Disconnect from the database when model.create is complete so the process is free to exit.
To add to Kaiser's answer, if you are on Windows using cmd, the single/double quotes are important. Put the double quotes on the outside, i.e.
node -e "require('./test').demo()"

Categories

Resources