【问题标题】:Testing a callback nested in a promise测试嵌套在 Promise 中的回调
【发布时间】:2017-11-13 23:13:36
【问题描述】:

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

saveDataToGoogleSpreadSheet(conversationData){
  return new Promise((resolve, reject) => {
    Spreadsheet.load(this.getGoogleAPISettings(), (err, spreadsheet) => {
      if (err) {
        return reject(err);
      }

      return spreadsheet.receive((receivedError, rows, info) => {
        if (receivedError) {
          return reject(receivedError);
        }
        const rowData = this.getSpreadsheetRowData(conversationData, info.totalRows);
        spreadsheet.add(rowData);
        return spreadsheet.send(sendError => (sendError ? reject(sendError) : resolve()));
      });
    });
  });
}

我测试了函数的案例一和案例二(两个第一个错误),但我无法为最后一个,我们在电子表格中添加一行的成功案例。

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

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

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

【问题讨论】:

  • 由于您没有告诉我们该功能必须做什么,所以没有人可以告诉您如何测试它。
  • @Raedwald 我同意这个问题的信息有点短,但它包含的足够多。他问他如何测试spreadsheet.add 方法是否在spreadsheet.receive 方法成功时被调用。
  • @laurent miller:您能说明一下您是如何测试前两个案例的吗?我试图在我的问题中猜测它,并且我假设您已经使用实际的网络调用进行了测试。这是正确的,如果不是,如何?如果它没有以某种方式回答您的问题,您也可以对答案发表评论。
  • it('应该在 Google 电子表格中添加一行', (done) => { nock('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('不应该做出调用'))) .catch((err) => { expect(err).to.equal('读取电子表格时出错'); done(); }); }).timeout(4000);这就是我测试它们的方式,抱歉格式奇怪,无法更改。
  • @oligofren 感谢您的帮助伙伴,我将完全使用您提供给我的信息。我赞成你的回答,但我认为这不会改变公开显示的分数,因为我有声誉

标签: node.js unit-testing mocha.js sinon


【解决方案1】:

很难从您拥有的小代码中判断测试的问题是什么,并且没有关于各种对象是什么以及它们如何产生的背景,所以我将假设Spreadsheet 是一个对象它是通过您需要的库创建的,除此之外,所有其他对象都是由模块创建的。即我假设您在某处有类似这样的线:

const Spreadsheet = require('some-google-docs-spreadsheet-lib');

这意味着一个问题是找出如何控制Spreadsheet 对象,以便我们可以消除它的行为。

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

据我所知,您可能已经使用了其中一种技术,正如您所说,您已经能够测试这两种错误情况。但也许您并没有真正进行单元测试,而是对服务进行了实际的网络调用(这更像是一个集成测试)?无论如何,我假设不会超过我上面写的内容,并向您展示如何使用 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 docs for the stub API

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

【讨论】:

  • 我尽量保持完整的信息,在此处提供所有相关信息(不在链接中),然后我回答问题。
猜你喜欢
  • 2018-10-06
  • 2013-03-30
  • 2018-10-19
  • 2019-11-27
  • 2017-03-22
  • 2018-09-19
  • 2020-10-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多