node.js - 在测试中模拟对外部服务的 axios 请求
问题描述
我正在尝试模拟从 NodeJS express 对外部服务的调用。我无法让 axios-mock-adapter 拦截实际的 axios 调用(http://api.openweathermap.org)并返回模拟响应。当断言完成时,它会失败,因为值不同。调用的温度是实际的外部温度,而不是模拟的温度。不知道我是完全关闭还是要接近我看不到的解决方案。对 JavaScript 和 NodeJS 来说有点新。
请 Stackoverflow,你是我唯一的帮助。
这是我的代码:
要测试的文件:
WeatherTools.prototype.getWeather = new Promise(function(resolve, reject) {
axios.get(config.weather.openWeatherLocationURL, {
params: {
id: config.weather.openWeatherMapLocation,
APPID: config.weather.openWeatherMapApiKey,
units: config.weather.openWeatherUnit
}
}
).then(function(axiosResponse) {
resolve(axiosResponse.data);
}).catch(function(axiosError) {
reject(axiosError);
});
});
测试文件:
const assert = require('assert');
const weatherTool = require('./weatertools');
const axios = require('axios');
let MockAdapter = require('axios-mock-adapter');
const TestData = require('./testData.js');
let mock = new MockAdapter(axios);
describe("Testing weather tools", () => {
beforeEach(function() {
mock
.onGet(config.weather.openWeatherLocationURL, {
params: {
id: config.weather.openWeatherMapLocation,
APPID: config.weather.openWeatherMapApiKey,
units: config.weather.openWeatherUnit
}
}).reply(200, TestData.location().mockedResponseData);
});
it('given a correct call to openWeather a valid response should be returned xxx', function(done) {
weatherTool.WeatherTools.getWeather.then(function(actual) {
assert.strictEqual(actual.temp.currentTemp, TestData.location().expected.temp.currentTemp);
done();
})
});
});
配置文件:
config.weather.openWeatherMapApiKey = 'theSecretApiKeyOfMine';
config.weather.openWeatherMapLocation = '1234567';
config.weather.openWeatherUnit = 'metric';
config.weather.openWeatherLocationURL = 'http://api.openweathermap.org/data/2.5/weather';
解决方案
问题出在经过测试的代码中。预计getWeather
member 是一种获取天气的方法,而它是 promise 属性。它没有天气,它实际上是天气。由于它是prototype
属性,它急切地执行对类定义的请求,即一旦导入类。这也意味着将来无法更新数据,即使需要这样做。
由于请求是热切执行的,因此不会受到 Axios mock 的影响。
getWeather
也使用 promise 构造反模式;axios
已经返回了一个承诺,没有必要用new Promise
.
它应该是:
WeatherTools.prototype.getWeather = () => {
return axios.get(config.weather.openWeatherLocationURL, {
params: {
id: config.weather.openWeatherMapLocation,
APPID: config.weather.openWeatherMapApiKey,
units: config.weather.openWeatherUnit
}
}
).then(function(axiosResponse) {
return axiosResponse.data;
});
});
所以它可以像weatherToolsInstance.getWeather().then(...)
. 预计这样使用axios-mock-adapter
时会被嘲笑。
推荐阅读
- javascript - 为什么我的 Discord 机器人会从其他渠道删除消息而不向变量添加值?
- python - Python程序实现一个矩阵来表示树的父-(子)子关系
- reactjs - 尝试将 React Spring 与 Semantic UI React 一起使用,简单示例
- django - Django如何将旧格式的url转换为新的格式路径
- javascript - React - Elements UI - 通过包装 div 大小隐藏的下拉菜单
- c++ - 如何在 C++ 中将十六进制 shellcode 字符串转换为无符号字符数组?
- javascript - 准备报告数据的功能性 Javascript map/reduce
- swift - 使用 SF 符号时调整 UImage 的大小 - UIImage(systemName:)
- javascript - Web 组件(JavaScript 原生)命名限制?
- ios - Xcode 11.4 - 终端介绍