2015-10-06 163 views
4

我想了解在测试的NodeJS承诺,和测试,我已经在其他语言中使用的方法,在这里没有我有点。基本的问题是“我怎么有效地测试在一个或多个链接的,然后(和完成或挂钩)承诺块间接投入和产出?”测试中承诺的NodeJS

这里的lib/test.js来源:

var Bluebird = require("bluebird"), 
    fs = Bluebird.promisifyAll(require("fs")); 

function read(file) { 
    return fs.readFileAsync(file) 
     .then(JSON.parse) 
     .done(function() { 
      console.log("Read " + file); 
     }); 
} 

function main() { 
    read("test.json"); 
} 

if (require.main === module) { 
    main(); 
} 

module.exports = read; 

而这里的tests/test.js

var Bluebird = require("bluebird"), 
    chai = require("chai"), 
    expect = chai.expect, 
    sinon = require("sinon"), 
    sandbox = sinon.sandbox.create(), 
    proxyquire = require("proxyquire"); 

chai.use(require("chai-as-promised")); 
chai.use(require("sinon-chai")); 

describe("test", function() { 
    var stub, test; 

    beforeEach(function() { 
     stub = { 
      fs: { 
       readFile: sandbox.stub() 
      } 
     } 
     test = proxyquire("../lib/test", stub); 
    }); 

    afterEach(function() { 
     sandbox.verifyAndRestore(); 
    }); 

    it("reads the file", function() { 
     test("test.json"); 
     expect(stub.fs.readFile).to.have.been.calledWith("test.json"); 
    }); 
    it("parses the file as JSON", function() { 
     stub.fs.readFileAsync = sandbox.stub().returns(Bluebird.resolve("foo")); 
     sandbox.stub(JSON, "parse"); 
     test("test.json"); 
     expect(JSON.parse).to.have.been.calledWith("foo"); 
    }); 
    it("logs which file was read", function() { 
     stub.fs.readFileAsync = sandbox.stub(); 
     sandbox.stub(JSON, "parse"); 
     test("bar"); 
     expect(console.log).to.have.been.calledWith("Read bar") 
    }); 
}); 

我意识到,这些例子是微乎其微的,做作的来源,但我希望尝试和理解如何测试承诺链,而不是如何读取文件并将其解析为JSON。 :)

另外,我没有绑定到任何框架或类似的东西,所以如果我在抓取任何包含的NodeJS库时无意中选择了糟糕的内容,那么也将赞赏召唤出来。

谢谢!

回答

2

假设语法是摩卡,你需要回报的承诺。当所有的承诺都按照返回值的方式工作时,如果你不从测试中返回它们,那么测试库就不能挂钩它们。

describe("testing promises with mocha",() => { 
    it("works by returning promises",() => { 
     return Promise.resolve("This test passes"); 
    }); 
    it("fails by returning promises",() => { 
     return Promise.reject(Error("This test fails")); 
    }); 
    it("Lets you chain promises",() => { 
     return fs.readFileAsync("test.json").then(JSON.parse); 
    }); 
}); 

(新功能箭头语法工程的NodeJS,如果你需要支持旧节点 - 将其转换为function(){电话)

+0

谢谢。我仍然使用NodeJS的v0.12.2,所以我还不能使用胖箭头。 –

1

@Benjamin Gruenbaum

我结束了在下面去lib/test.js

var Bluebird = require("bluebird"), 
    fs = Bluebird.promisifyAll(require("fs")); 

function read(files) { 
    return Bluebird.map(files, function (file) { 
     return fs.readFileAsync(file) 
      .then(JSON.parse) 
      .then(function (data) { 
       console.log("Read " + file); 
      }); 
    }); 
} 

function main() { 
    read(["test.json", "test2.json"]); 
} 

if (require.main === module) { 
    main(); 
} 

module.exports = read; 

这是tests/test.js

var Bluebird = require("bluebird"), 
    chai = require("chai"), 
    chaiAsPromised = require("chai-as-promised"), 
    expect = chai.expect, 
    sinon = require("sinon"), 
    sandbox = sinon.sandbox.create(), 
    proxyquire = require("proxyquire"); 

chai.use(chaiAsPromised); 
chai.use(require("sinon-chai")); 

describe("test", function() { 
    var stub, test; 

    beforeEach(function() { 
     stub = { 
      fs: { 
       readFile: sandbox.stub() 
      } 
     }; 
     sandbox.stub(JSON, "parse"); 
     test = proxyquire("../lib/test", stub); 
     stub.fs.readFileAsync = sandbox.stub().returns(Bluebird.resolve()); 
    }); 

    afterEach(function() { 
     sandbox.verifyAndRestore(); 
    }); 

    it("reads the files", function() { 
     var files = ["test.json", "test2.json"]; 
     return test(files).then(function() { 
      var expects = files.map(function (file) { 
       return expect(stub.fs.readFileAsync).to.have.been.calledWith(file); 
      }); 
      // expects.push(expect(Bluebird.resolve(1)).to.eventually.equal(2)); 
      return Bluebird.all(expects); 
     }); 
    }); 
    it("parses the files as JSON", function() { 
     var returns = ["foo", "bar"]; 
     returns.forEach(function (value, index) { 
      stub.fs.readFileAsync.onCall(index).returns(Bluebird.resolve(value)); 
     }); 
     return test(["baz", "buz"]).then(function() { 
      var expects = returns.map(function (value) { 
       return expect(JSON.parse).to.have.been.calledWith(value); 
      }) 
      // expects.push(expect(Bluebird.resolve(1)).to.eventually.equal(2)); 
      return Bluebird.all(expects); 
     }); 
    }); 
    it("logs which files were read", function() { 
     var files = ["bleep", "blorp"]; 
     sandbox.spy(console, "log"); 
     return test(files).then(function() { 
      var expects = files.map(function (file) { 
       return expect(console.log).to.have.been.calledWith("Read " + file); 
      }); 
      // expects.push(expect(Bluebird.resolve(1)).to.eventually.equal(2)); 
      return Bluebird.all(expects); 
     }); 
    }); 
}); 

我在那里留下了注释掉的1 === 2断言,以确保我没有得到误报(例如当.then不会被调用,因为我做错了)。

+0

这看起来像一个完美的解决方案。干杯。 –