Mocha,Sinon和Chai在回调中测试两个http调用

时间:2018-05-25 21:34:31

标签: node.js mocha sinon

我正在与Chai Mocha和Sinon进行一些非常简单的测试。我想知道如何测试在回调中调用的http方法。如果可以,请指出正确的方向,努力寻找任何东西,我知道你可以做到,只是不确定如何。我的代码如下:

index.js

const http = require('http')

class Index {
  add(a, b) {
    return a + b
  }

  get(uri) {
    http.get(uri, () => {
      http.get('/', function() {
        return
      })
    })
  }
}

module.exports = Index

index.spec.js

const Index = require('../index')
const http = require('http')
const { stub, fake, assert } = require('sinon')
const { expect } = require('chai')

let httpSpy;

beforeEach(function () {
  a = new Index()
  httpSpy = stub(http, 'get')
})

describe('When the get method is invoked', function () {
  beforeEach(function () {
    a.get('http://www.google.co.uk')
  })

  it('should make a call to the http service with passed in uri', function () {
    assert.calledOnce(httpSpy) // This really should be called twice (Part I am struggling with)
    assert.calledWith(httpSpy, 'http://www.google.co.uk')
    // I want to test instead that the httpSpy was called twice as, inside the get method, when the first http get resolves, another one gets fired off also
  })
})

1 个答案:

答案 0 :(得分:2)

有两个问题。

首先,我们无法判断Index.get()方法执行何时结束(它不接受回调,既不返回承诺,也不标记为异步等)。

get(uri) { ... }

使用这种方法非常不方便。例如:如果我们想首先执行Index.get(),然后在我们无法完成后立即采取行动。

要解决此问题,我们只需添加一个回调作为Index.get的最后一个参数。

第二个问题是http.get方法是如何存根的:

httpSpy = stub(http, 'get')

这一行基本上意味着:用空函数替换http.get。如果您在中传递回调但是它不会调用它,那么虚拟函数不会抛出。

这就是http.get只被调用一次的原因。它只是忽略了第二次应该调用http.get的传递回调。

为了解决这个问题,我们可以使用stub.yields()方法让sinon意识到传递给存根的最后一个参数是一个回调(而sinon需要调用它)。您可以在the docs中找到该方法。

以下是一个工作示例,请参阅我的评论:



class Index {
    // Added a callback here
    get(uri, callback) {
        http.get(uri, () => {
            http.get('/', () => {
                // Pass any data you want to return here
                callback(null, {});
            })
        })
    }
}

let httpSpy;

beforeEach(() => {
    a = new Index()
    // Now sinon will expect a callback as a last parameter and will call it
    httpSpy = stub(http, 'get').yields();
})

describe('When the get method is invoked', () => {
    const uri = 'http://www.google.co.uk';

    // Now we are waiting for the execution to end before any assertions
    beforeEach(done => {
        a.get(uri, done);
    });

    it('should make a call to the http service with passed in uri', () => {
        assert.calledTwice(httpSpy);
        assert.match(httpSpy.getCall(0).args[0], uri);
        assert.match(httpSpy.getCall(1).args[0], '/');
    });
})