我正在与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
})
})
答案 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], '/');
});
})