Monday, May 20, 2024
56
rated 0 times [  62] [ 6]  / answers: 1 / hits: 10802  / 3 Years ago, wed, june 30, 2021, 12:00:00

I've created a very small app that calculates the total price to pay for certain crypto if you pass in the coin and quantity. I want to test for errors but I am always getting "Received promise resolved instead of rejected". I believe this is due to the fact that if the url is wrong axios still resolves the promise.


The second problem I have is that I have tried testing if the url is correct but I have an issue that headers are part of the url and I can't see to figure out how to test just the url path without headers.


Those are tests 2 and 3 (Test number 1 is working)


// 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()),
};

To recap, test 1 passes, test 2 fails with "Received promise resolved instead of rejected" and test 3 fails as I am getting headers as well not just url.


More From » unit-testing

 Answers
0

You should mock axios.get() with resolved/rejected value. Since you use the try...catch... statement, the error is thrown by axios.get() method will be caught, and you didn't rethrow any errors. So the assertion of test case 2 will not match toThrowError. Instead, you can use jest.spyOn() to add spy to console.log, and assert it to be called with the mocked Error.


Here is an solution only using jest.mock('axios') to mock axios module without __mocks__/axios.js file.


E.g.


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' } });
});
});

test result:


 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

[#1155] Friday, June 25, 2021, 3 Years  [reply] [flag answer]
Only authorized users can answer the question. Please sign in first, or register a free account.
luna

Total Points: 698
Total Questions: 114
Total Answers: 93

Location: Israel
Member since Wed, Apr 14, 2021
3 Years ago
luna questions
;