包含承诺的单元测试处理程序
Unit test handler that contains promise
我有 TDD 知识,并且我一直在尝试应用相同的原则 javascript 开始一个项目。
我正在构建一个 API,一旦命中,就会向外部服务发出请求以收集一些数据,一旦检索到,就会解析它并 returns 响应。
到目前为止,我的传奇一直很不走运,我搜索了很多,我在 SO 上发现的最相似的问题是这个 。但是我没有成功应用相同的解决方案。
我在实现端的实现如下:
//... other handlers
weather(request, response) {
//... some setup and other calls
this.externalService.get(externalURL)
.then(serviceResponse => {
this.externalResponseParser.parse(serviceResponse)
});
//... some more code
}
而在测试方面:
let requester;
let mockParser;
let handler;
let promiseResolve;
let promiseReject;
beforeEach(function () {
requester = new externalRequesterService();
mockParser = sinon.createStubInstance(...);
handler = new someHandler({
externalService: requester,
externalResponseParser: mockParser
});
});
it('returns data', function () {
sinon.stub(requester, 'get').callsFake((url) => {
return new Promise((resolve, reject) => {
// so I can be able to handle when the promise gets resolved
promiseResolve = resolve;
promiseReject = reject;
});
});
handler.weather(request, response);
// assertions of what happens before externalService.get gets called - all green
promiseResolve(expectedServiceResponse);
assert.ok(mockExternalResponseParser.parse.calledOnce, 'Expected externalResponseParser.parse to have been called once');
});
在测试的最后一行,它失败了,即使我正在调用我应该调用的。
在某些时候,我添加了一些日志记录,我能够看到 then
块的代码似乎是在测试断言之后执行的,这可能是问题的根源。
我试图找出是否有某种 eventually
可以使用,所以我在解决承诺后的断言是这样的:
assert.eventually(mockExternalResponseParser.parse.calledOnce, 'Expected externalResponseParser.parse to eventually be called once');
但运气不好。
有没有人对缺少的内容有明确的解释?非常感谢
P.S.- 根据要求,请找到我的代码 here 的精简版本。只需 运行 npm install
,然后是 npm test
以获得相同的输出。
感谢大家抽出时间。
我最终在 Medium 上找到了这篇非常好的文章,它让我解决了我的问题。它有一个很好的解释,从回调到承诺,这正是我手头的场景。
我已经更新了我创建的关于如何修复它的 github 存储库。
如果您想要 TL;DR,这里只是更改的重点。实施方:
async weather(request, response) {
//...
let serviceResponse = await this.requesterService.get(weatherURL);
//...
};
而在测试方面:
it('returns weather on success', async function () {
sinon.stub(requester, 'get').callsFake((_) => {
return new Promise((resolve, _) => {
resolve(expectedServiceResponse);
});
});
await handler.weather(request, response);
//...
assert.ok(mockWeatherParser.parseWeather.calledOnce, 'Expected WeatherParser.parseWeather to have been called once'); // no longer fails here
//...
});
请记住,在这个例子中,它仍然是同步的。然而,我已经一步一步地改进了我的 API,并且在使用 Promises 迁移到这个同步版本之后,迁移到异步版本要容易得多。无论是在测试还是在实施方面。
如果您遇到同样的问题并需要帮助或有任何疑问,请告诉我。我很乐意提供帮助。
我有 TDD 知识,并且我一直在尝试应用相同的原则 javascript 开始一个项目。
我正在构建一个 API,一旦命中,就会向外部服务发出请求以收集一些数据,一旦检索到,就会解析它并 returns 响应。
到目前为止,我的传奇一直很不走运,我搜索了很多,我在 SO 上发现的最相似的问题是这个
我在实现端的实现如下:
//... other handlers
weather(request, response) {
//... some setup and other calls
this.externalService.get(externalURL)
.then(serviceResponse => {
this.externalResponseParser.parse(serviceResponse)
});
//... some more code
}
而在测试方面:
let requester;
let mockParser;
let handler;
let promiseResolve;
let promiseReject;
beforeEach(function () {
requester = new externalRequesterService();
mockParser = sinon.createStubInstance(...);
handler = new someHandler({
externalService: requester,
externalResponseParser: mockParser
});
});
it('returns data', function () {
sinon.stub(requester, 'get').callsFake((url) => {
return new Promise((resolve, reject) => {
// so I can be able to handle when the promise gets resolved
promiseResolve = resolve;
promiseReject = reject;
});
});
handler.weather(request, response);
// assertions of what happens before externalService.get gets called - all green
promiseResolve(expectedServiceResponse);
assert.ok(mockExternalResponseParser.parse.calledOnce, 'Expected externalResponseParser.parse to have been called once');
});
在测试的最后一行,它失败了,即使我正在调用我应该调用的。
在某些时候,我添加了一些日志记录,我能够看到 then
块的代码似乎是在测试断言之后执行的,这可能是问题的根源。
我试图找出是否有某种 eventually
可以使用,所以我在解决承诺后的断言是这样的:
assert.eventually(mockExternalResponseParser.parse.calledOnce, 'Expected externalResponseParser.parse to eventually be called once');
但运气不好。
有没有人对缺少的内容有明确的解释?非常感谢
P.S.- 根据要求,请找到我的代码 here 的精简版本。只需 运行 npm install
,然后是 npm test
以获得相同的输出。
感谢大家抽出时间。
我最终在 Medium 上找到了这篇非常好的文章,它让我解决了我的问题。它有一个很好的解释,从回调到承诺,这正是我手头的场景。
我已经更新了我创建的关于如何修复它的 github 存储库。
如果您想要 TL;DR,这里只是更改的重点。实施方:
async weather(request, response) {
//...
let serviceResponse = await this.requesterService.get(weatherURL);
//...
};
而在测试方面:
it('returns weather on success', async function () {
sinon.stub(requester, 'get').callsFake((_) => {
return new Promise((resolve, _) => {
resolve(expectedServiceResponse);
});
});
await handler.weather(request, response);
//...
assert.ok(mockWeatherParser.parseWeather.calledOnce, 'Expected WeatherParser.parseWeather to have been called once'); // no longer fails here
//...
});
请记住,在这个例子中,它仍然是同步的。然而,我已经一步一步地改进了我的 API,并且在使用 Promises 迁移到这个同步版本之后,迁移到异步版本要容易得多。无论是在测试还是在实施方面。
如果您遇到同样的问题并需要帮助或有任何疑问,请告诉我。我很乐意提供帮助。