6

I'm using Mocha and Chai with a node project and wondering how do I test the error callback in node functions?

Here is an example of my code that I want to test:

  savePlayer: function(player) {

  var playerName =  player.name;

    modules.fs.writeFile('./Data/' + playerName + '.json', JSON.stringify(player), function (err) {
      if (err) {
        return console.log(err.message);
      }
    });
}

This is my test:

describe("savePlayer", function() {
  it("Should save the player in JSON, using thier name", function() {

     var player = {name: "test" }

    modules.data.savePlayer(player);

   var playerFile =  modules.fs.readFileSync('Data/test.json').toString('utf8');

    expect(playerFile).should.exist;

  });
});

This passes, but I want full code coverage. This line return console.log(err.message); is untested and I'm unsure how to fake an error and test that the console reported an error.

2
  • Depending on how you're writing your code you need to rewire it to return a moch or inject a mock into your savePlayer function Commented Nov 30, 2015 at 12:48
  • is that testing of core API fs ? Commented Nov 30, 2015 at 13:22

2 Answers 2

8

Here's an annotated example using sinon and chai:

var fs         = require('fs');
var sinon      = require('sinon');
var expect     = require('chai').expect;
var savePlayer = require('your-module').savePlayer;

describe('savePlayer', function() {
  // We spy on `console.log()` calls. Spying means that calls to this function
  // are recorded, and we can check to see if it, for instance, was called with
  // particular arguments.
  var consoleSpy = sinon.spy(console, 'log');

  // We stub `fs.writeFile()`. Stubbing means that calls to this function 
  // are taken over, and we can determine exactly how it should act.
  var fsStub     = sinon.stub(fs, 'writeFile');

  // Before each test, the spy and stub are reset.
  beforeEach(function() {
    consoleSpy.reset();
    fsStub.reset();
  });

  // After _all_ tests, the original functions are restored.
  after(function() {
    consoleSpy.restore();
    fsStub.restore();
  });

  // Test #1: if `fs.writeFile()` fails, it should trigger a call to `console.log`.
  it('should log an error when `fs.writeFile` fails', function() {
    var msg = 'my test error';

    // Here we let `fs.writeFile()` call the callback with an error.
    fsStub.yields( new Error(msg) );

    // Call your function.
    savePlayer({ name : 'xx' });

    // Check to make sure that `console.log()` is called with the same error message.
    expect( consoleSpy.calledWith(msg) ).to.be.true;
  });

  // Test #2: when `fs.writeFile()` went okay, nothing should be logged.
  it('should not log an error when `fs.writeFile` is okay', function() {
    // As per Node convention, falsy first argument means 'no error'.
    fsStub.yields( null );

    // Call your function.
    savePlayer({ name : 'xx' });

    // We expect that `console.log()` wasn't called.
    expect( consoleSpy.called ).to.be.false;
  });

});
Sign up to request clarification or add additional context in comments.

Comments

0

if you are working on unit-test, you need to make sure that everything is isolated. it means that no 3rd party or back-end connection.

so you need to stub all of them.

your main module file will look like ==>

 savePlayer: function(player) {

  var playerName =  player.name;

    modules.fs.writeFile('./Data/' + playerName + '.json', JSON.stringify(player), function (err) {
      if (err) {
        // throw error message
        throw new Error(err.message);
      }
    });
}

sample code ==>

const fs = require('fs')
const sinon = require('sinon')

describe("savePlayer", () => {
  it("Should save file successfully", done => {

     // stub all external connections (your external file)
     const fsStub = fs.stub(fs, 'writeFile')

     // expect save success
     fsStub.yields(null)

     // declare param
     const player = {name: "test" } 

     // execute function
     modules.data.savePlayer(player)

     // test
     expect(fsStub.called).to.be.true

     // clean
     fsStub.restore();
     done();
  });

  it("Should get error", done => {

     // stub all external connections (your external file)
     const fsStub = fs.stub(fs, 'writeFile')

     // expect error
     fsStub.yields(new Error('SOME ERROR OCCURS'))

     // declare param
     const player = {name: "test" } 

     // execute function
     try {
         modules.data.savePlayer(player)
     } catch(e) {
         // test
         expect(e.message).eql('SOME ERROR OCCURS');

         // clean
         fsStub.restore();
         done();
     }
  });
});

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.