Mocha、Sinon 和 Chai 在回调中测试两个 http 调用
Mocha, Sinon and Chai testing two http calls inside a callback
我正在用 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
})
})
有两个问题。
首先,我们无法判断 Index.get()
方法执行何时结束(它不接受回调,return 承诺,不标记为异步等)。
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], '/');
});
})
我正在用 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
})
})
有两个问题。
首先,我们无法判断 Index.get()
方法执行何时结束(它不接受回调,return 承诺,不标记为异步等)。
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], '/');
});
})