node.js - Mocha、Sinon 和 Chai 在回调中测试两个 http 调用
问题描述
我正在用 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()
方法执行何时结束(它不接受回调,不返回承诺,不标记为异步等)。
get(uri) { ... }
这种方法的使用极其不方便。例如:如果我们想先做Index.get()
,然后在我们做不到之后立即做一些动作。
为了解决这个问题,我们可以添加一个回调作为Index.get
.
第二个问题是该http.get
方法是如何被存根的:
httpSpy = stub(http, 'get')
这一行的基本意思是:http.get
用一个空函数替换。如果您在内部传递回调,则该虚拟函数不会抛出,但不会调用它。
这就是为什么http.get
只调用一次。它只是忽略了http.get
第二次应该调用的传递的回调。
为了解决这个问题,我们可以使用stub.yields()
方法让 sinon 知道传递给存根的最后一个参数是回调(并且 sinon 需要调用它)。您可以在文档中找到该方法。
这是一个工作示例,请参阅我的评论:
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], '/');
});
})
推荐阅读
- java - Vert.x 线程命名 - “vert.x-worker-thread-...”
- visual-studio - 在 VS 的 MSI 设置中强制文件随 Windows 自动启动
- c# - why I couldn't see the referenced dll module hosted by a process
- sql - Oracle - 按日期区分组
- java - how can i still get this problem after i mention the service in the manifest
- javascript - How do I use requirejs in the browser?
- r - Generate Absolute xpath of given webElement in RSelenium [R]
- bash - How to run commands after login to shell command of a container in a VM?
- java - 除非我使用 .join(),否则为什么同步方法不会被锁定?
- css - 适合在 Flexbox/Grid 中缩放的图像行?