测试嵌套在promise中的回调 [英] Testing a callback nested in a promise

查看:83
本文介绍了测试嵌套在promise中的回调的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

我测试了函数的第一种情况和第二种情况(前两个错误),但对于最后一个情况我却做不到,成功的情况是我们在电子表格中添加了一行.

I tested the case one and case two of the function (the two first errors) but I couldn't do it for the last one, the case of success where we an add a row to a spreadsheet.

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

I need some help with the structure of the test, or a hint on how could my test be.

以前的测试是如何进行的

how the previous tests were made

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

推荐答案

很难从您拥有的小代码中分辨出测试的问题,并且没有关于各种对象的含义以及它们如何产生的背景知识因此,我仅假设Spreadsheet是通过所需的库创建的对象,除此之外,所有其他对象均由模块创建.即我假设您某处的线条类似于以下内容:

It is hard to tell what is the problem with the test from the little code you have, and no background on what the various objects are and how they come to be, so I will just assume that Spreadsheet is an object that is created through a library you require, and other than that, all other objects are created by the module. i.e. I assume you somewhere have a line resembling something like this:

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

这意味着一个问题是找出如何控制Spreadsheet对象,以便我们了解其行为.

That means one problem is finding out how to control the Spreadsheet object so we can stub out its behavior.

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

Just to start you out, you might get some good pointers on general code and test structure for easy testing from these two answers, as they cover the two most relevant techniques: dependency injection and exploiting link seams.

  • Mocking Redis Constructor with Sinon
  • How to test an ES6 class that needs jquery?

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

For all I know, you might already utilize one of these techniques, as you say you have been able to test the two error situations. But maybe you have not really been unit testing and done the actual network calls to the service instead (which is more of an integration test)? Anyway, I'll assume no more than what I wrote above and show you how to do the testing using 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
});

请参阅有关存根API的Sinon文档.

揭露:我是Sinon维护团队的成员.

Disclosure: I am part of the Sinon maintainer team.

这篇关于测试嵌套在promise中的回调的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆