Node.js 测试嵌套在承诺中的回调

Node.js 测试嵌套在承诺中的回调,node.js,unit-testing,mocha.js,sinon,Node.js,Unit Testing,Mocha.js,Sinon,tl;dr我需要测试我的方法是否在成功加载Google电子表格时向电子表格添加一行 我测试了函数的案例一和案例二(前两个错误),但最后一个测试失败了,我们成功地在电子表格中添加了一行 我需要一些关于测试结构的帮助,或者关于我的测试如何进行的提示 编辑:以前的测试是如何进行的 it('should add a row to a Google Spreadsheet', (done) => { nock('https://spreadsheets.google.com')

tl;dr我需要测试我的方法是否在成功加载Google电子表格时向电子表格添加一行

我测试了函数的案例一和案例二(前两个错误),但最后一个测试失败了,我们成功地在电子表格中添加了一行

我需要一些关于测试结构的帮助,或者关于我的测试如何进行的提示

编辑:以前的测试是如何进行的

it('should add a row to a Google Spreadsheet', (done) => {
      nock('https://spreadsheets.google.com')
      .post('/feeds/cells/1ZOd7Sysc-JNa-D5AHb7ZJkwBRMBGaeKpzIwEl7B8RbQ/1/private/full/batch')
      .replyWithError({ message: 'abcde' });
      api.saveDataToGoogleSpreadSheet({ data: 'some data' })
      .then(() => done(new Error('should not have made the call')))
      .catch((err) => {
        expect(err).to.equal('Error Reading Spreadsheet');
        done();
      });
    }).timeout(4000);

从您拥有的小代码很难判断测试的问题是什么,并且没有关于各种对象是什么以及它们是如何形成的背景,因此我将假设
电子表格
是通过您需要的库创建的对象,除此之外,所有其他对象都是由模块创建的。i、 e.我假设你在某处有一条类似这样的线:

const Spreadsheet = require('some-google-docs-spreadsheet-lib');
这意味着一个问题是如何控制
电子表格
对象,这样我们就可以删除它的行为

首先,您可能会从这两个答案中获得一些关于通用代码和测试结构的好的指导,以便于测试,因为它们涵盖了两种最相关的技术:依赖项注入和利用链接接缝

据我所知,您可能已经使用了其中一种技术,正如您所说,您已经能够测试这两种错误情况。但是,也许您没有真正进行单元测试,而是对服务进行了实际的网络调用(这更像是一个集成测试)?无论如何,我将假设我上面写的内容,并向您展示如何使用
proxyquire
进行测试:

const assert = require('assert');
const dummy = ()=> {};
const SpreadSheetStubLibrary = { load: dummy };
const MyClassToTest = proxyquire('../src/my-module', { 
    'some-google-docs-spreadsheet-lib': SpreadSheetStubLibrary
})
const config = {};
const conversationData = {};

let stubSetup;
let spreadsheet;
let myObj;

function setupStubs() {
    stubSetup = stubSpreadsheetLoadFunction();
    spreadsheet = stubSetup.spreadsheet;
    SpreadSheetStubLibrary.load = stubSetup.load;

    myObj = new MyClassToTest(config);
    conversationData = {};
};

function createSpreadsheetStubObj(){
    return {
        receive: sinon.stub(),
        add: sinon.stub(),
        send: sinon.stub()
    }
}

function stubSpreadsheetLoadFunction(){
    const spreadsheet = createSpreadsheetStubObj();

    return { 
        load: (settings, cb) => cb(null, spreadsheet),
        spreadSheetStubObj: spreadsheet
    };
}


it('should add a row to the spreadsheet on successful load', () => {
    // Arrange
    setupStubs();
    const rowData = { foo: 1, bar: 2};
    spreadsheet.receive.yields(); // calls any callback given
    myObj.getSpreadsheetRowData = () => rowData; // see lines below

    // if you want to use the real getSpreadsheetRowData, uncomment these lines
    //const rows = []; // not used in the method?
    //const info = { totalRows : 100 };
    //spreadsheet.receive.yields(null, rows, info);

    // Act
    return myObj.saveDataToGoogleSpreadSheet(conversationData).then(()=>{
        // Assert
        assert(spreadsheet.add.calledOnce);
        assert(spreadsheet.add.calledWith(rowData));
    });
});


it('should add a row to the spreadsheet on successful load', () => {
    // reuse the above
});


披露:我是Sinon维护团队的一员。

因为您没有告诉我们函数必须做什么,没有人能告诉您如何测试它。@Raedwald我同意这个问题的信息有点少,但它包含的内容足够了。他问他如何测试
电子表格.add
方法是否在
电子表格.receive
方法成功后被调用。@laurent miller:你能说明你是如何测试前两个案例的吗?我试着在我的问题中猜测它,我假设您已经使用实际的网络呼叫进行了测试。这是正确的吗?如果不是,怎么做?如果答案没有回答您的问题,您也可以对其进行评论。它('应该在谷歌电子表格中添加一行',(完成)=>{nock(').post('/feeds/cells/1ZOd7Sysc-JNa-d5ahb7zjkwbmbgaekpziwel7b8rbq/1/private/full/batch')。replywhitherror({message:'abcde'});api.savedatatogoglespreadsheet({data:'some data'})。然后(()=>done(新错误('不应该进行调用'))。catch((err)=>{expect(err).to.equal('Error Reading spreadset');done();});})。超时(4000);这就是我测试它们的方式,很抱歉格式很奇怪,无法更改。@Oligoren谢谢你的帮助,伙计,我会完全使用你提供给我的信息。我对你的答案投了赞成票,但我认为不会更改公开显示的分数,因为我有声誉。我试图让它充满信息,将所有相关信息告诉她e(不在链接中),我回答这个问题。
const assert = require('assert');
const dummy = ()=> {};
const SpreadSheetStubLibrary = { load: dummy };
const MyClassToTest = proxyquire('../src/my-module', { 
    'some-google-docs-spreadsheet-lib': SpreadSheetStubLibrary
})
const config = {};
const conversationData = {};

let stubSetup;
let spreadsheet;
let myObj;

function setupStubs() {
    stubSetup = stubSpreadsheetLoadFunction();
    spreadsheet = stubSetup.spreadsheet;
    SpreadSheetStubLibrary.load = stubSetup.load;

    myObj = new MyClassToTest(config);
    conversationData = {};
};

function createSpreadsheetStubObj(){
    return {
        receive: sinon.stub(),
        add: sinon.stub(),
        send: sinon.stub()
    }
}

function stubSpreadsheetLoadFunction(){
    const spreadsheet = createSpreadsheetStubObj();

    return { 
        load: (settings, cb) => cb(null, spreadsheet),
        spreadSheetStubObj: spreadsheet
    };
}


it('should add a row to the spreadsheet on successful load', () => {
    // Arrange
    setupStubs();
    const rowData = { foo: 1, bar: 2};
    spreadsheet.receive.yields(); // calls any callback given
    myObj.getSpreadsheetRowData = () => rowData; // see lines below

    // if you want to use the real getSpreadsheetRowData, uncomment these lines
    //const rows = []; // not used in the method?
    //const info = { totalRows : 100 };
    //spreadsheet.receive.yields(null, rows, info);

    // Act
    return myObj.saveDataToGoogleSpreadSheet(conversationData).then(()=>{
        // Assert
        assert(spreadsheet.add.calledOnce);
        assert(spreadsheet.add.calledWith(rowData));
    });
});


it('should add a row to the spreadsheet on successful load', () => {
    // reuse the above
});