admin管理员组

文章数量:1356522

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.

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.

Share Improve this question asked Nov 30, 2015 at 12:39 Liam KennethLiam Kenneth 9821 gold badge11 silver badges21 bronze badges 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 – Henrik Andersson Commented Nov 30, 2015 at 12:48
  • is that testing of core API fs ? – webduvet Commented Nov 30, 2015 at 13:22
Add a ment  | 

2 Answers 2

Reset to default 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;
  });

});

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();
     }
  });
});

本文标签: javascriptHow to test error callback in NodejsStack Overflow