2015-10-06 383 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

這看起來像一個完美的解決方案。乾杯。 –