我创建了一个非常小的应用程序,如果您传入硬币和数量,它会计算为某些加密货币支付的总价。我想测试错误,但我总是收到“收到的承诺已解决而不是被拒绝”。我相信这是因为如果 url 错误,axios 仍然可以解决承诺。
我遇到的第二个问题是,我已经尝试测试 url 是否正确,但是我遇到了一个问题,即标头是 url 的一部分,我无法弄清楚如何仅测试没有标头的 url 路径。
那些是测试 2 和 3(测试编号 1 有效)
// getTotalPrice.js
const axios = require("axios");
let symbol = process.argv[2];
let quantity = process.argv[3];
const API = `https://rest.coinapi.io/v1/exchangerate`;
const headers = {headers:{"X-CoinAPI-Key": "MY TOKEN"},};
const getTotalPrice = async (symbol = "BTC", quantity = 1) => {
try {
let res = await axios.get(`${API}/${symbol}/USD`, headers);
let data = res.data;
return Math.round(data.rate * quantity * 100) / 100;
} catch(err) {
console.log(err)
}
};
getTotalPrice(symbol, quantity);
module.exports = {
getTotalPrice,
API
};
// getTotalPrice.test.js
const { get, getError } = require("axios");
const { getTotalPrice } = require("../getTotalPrice");
describe("getTotalPrice", () => {
afterEach(() => {
get.mockClear();
});
it("fetches data successfully from an api", async () => {
const res = {
data: {
rate: 34000,
},
};
get.mockImplementation(() => Promise.resolve(res));
await expect(getTotalPrice()).resolves.toEqual(res.data.rate);
});
it("throws an error when incorrect data is passed", async () => {
const errorMessage = "Wrong inputs passed in";
getError.mockImplementationOnce(() => Promise.reject({}));
await expect(getTotalPrice()).rejects.toThrowError();
});
it("uses correct url", async () => {
const data = {
data: {
rate: 2000,
},
};
get.mockImplementationOnce(() => Promise.resolve(data));
await getTotalPrice("ETH");
expect(get).toHaveBeenCalledWith(
`${API}/ETH/USD`
);
});
});
// axios.js (in __mocks__)
module.exports = {
get: jest.fn(() => Promise.resolve({ data: {} })),
getError: jest.fn(() => Promise.reject()),
};
总而言之,测试 1 通过,测试 2 失败,并显示“收到的承诺已解决而不是被拒绝”,测试 3 失败,因为我不仅获取了 url,还获取了标头。
答案 0 :(得分:0)
您应该使用已解决/拒绝的值来模拟 axios.get()
。由于您使用了 try...catch...
语句,因此 axios.get()
方法抛出的错误将被捕获,并且您没有重新抛出任何错误。所以测试用例 2 的断言将不匹配 toThrowError
。相反,您可以使用 jest.spyOn()
将间谍添加到 console.log
,并断言它会被模拟的 Error
调用。
这是一个仅使用 jest.mock('axios')
模拟 axios
模块而没有 __mocks__/axios.js
文件的解决方案。
例如
getTotalPrice.js
:
const axios = require('axios');
let symbol = process.argv[2];
let quantity = process.argv[3];
const API = `https://rest.coinapi.io/v1/exchangerate`;
const headers = { headers: { 'X-CoinAPI-Key': 'MY TOKEN' } };
const getTotalPrice = async (symbol = 'BTC', quantity = 1) => {
try {
let res = await axios.get(`${API}/${symbol}/USD`, headers);
let data = res.data;
return Math.round(data.rate * quantity * 100) / 100;
} catch (err) {
console.log(err);
}
};
module.exports = { getTotalPrice, API };
getTotalPrice.test.js
:
const axios = require('axios');
const { getTotalPrice, API } = require('./getTotalPrice');
jest.mock('axios');
describe('getTotalPrice', () => {
it('fetches data successfully from an api', async () => {
const res = { data: { rate: 34000 } };
axios.get.mockResolvedValueOnce(res);
await expect(getTotalPrice()).resolves.toEqual(res.data.rate);
});
it('throws an error when incorrect data is passed', async () => {
const logSpy = jest.spyOn(console, 'log');
const err = new Error('Wrong inputs passed in');
axios.get.mockRejectedValueOnce(err);
await getTotalPrice();
expect(logSpy).toBeCalledWith(err);
});
it('uses correct url', async () => {
const res = { data: { rate: 2000 } };
axios.get.mockResolvedValueOnce(res);
await getTotalPrice('ETH');
expect(axios.get).toHaveBeenCalledWith(`${API}/ETH/USD`, { headers: { 'X-CoinAPI-Key': 'MY TOKEN' } });
});
});
测试结果:
PASS examples/68200193/getTotalPrice.test.js (7.527 s)
getTotalPrice
✓ fetches data successfully from an api (3 ms)
✓ throws an error when incorrect data is passed (14 ms)
✓ uses correct url (1 ms)
console.log
Error: Wrong inputs passed in
at /Users/dulin/workspace/github.com/mrdulin/jest-v26-codelab/examples/68200193/getTotalPrice.test.js:14:17
at Generator.next (<anonymous>)
at /Users/dulin/workspace/github.com/mrdulin/jest-v26-codelab/examples/68200193/getTotalPrice.test.js:8:71
at new Promise (<anonymous>)
at Object.<anonymous>.__awaiter (/Users/dulin/workspace/github.com/mrdulin/jest-v26-codelab/examples/68200193/getTotalPrice.test.js:4:12)
at Object.<anonymous> (/Users/dulin/workspace/github.com/mrdulin/jest-v26-codelab/examples/68200193/getTotalPrice.test.js:12:66)
at Object.asyncJestTest (/Users/dulin/workspace/github.com/mrdulin/jest-v26-codelab/node_modules/jest-jasmine2/build/jasmineAsyncInstall.js:106:37)
at /Users/dulin/workspace/github.com/mrdulin/jest-v26-codelab/node_modules/jest-jasmine2/build/queueRunner.js:45:12
at new Promise (<anonymous>)
at mapper (/Users/dulin/workspace/github.com/mrdulin/jest-v26-codelab/node_modules/jest-jasmine2/build/queueRunner.js:28:19)
at /Users/dulin/workspace/github.com/mrdulin/jest-v26-codelab/node_modules/jest-jasmine2/build/queueRunner.js:75:41
at console.<anonymous> (node_modules/jest-environment-enzyme/node_modules/jest-mock/build/index.js:866:25)
at Generator.throw (<anonymous>)
------------------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
------------------|---------|----------|---------|---------|-------------------
All files | 100 | 100 | 100 | 100 |
getTotalPrice.js | 100 | 100 | 100 | 100 |
------------------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests: 3 passed, 3 total
Snapshots: 0 total
Time: 8.034 s