Issue unit testing this function in node with node-fetch - javascript

I'm trying to unit test this function.... following the documentation.
Any ideas why i'm getting this error? According to the documentation we can see it being called this way... What am I missing. https://jestjs.io/docs/en/bypassing-module-mocks
Thankx
async function isValid(pair) {
const path = process.env.PATH;
const query = '/check';
const requestOptions = ccyServiceRequestOptions(pair);
try {
const response = await fetch(path + query, requestOptions);
const json = await response.json();
return json.result.pair === pair;
} catch (err) {
if (err instanceof TypeError) {
return false;
}
else {
log.error(err);
throw err;
}
}
}
------------------------------------------------------------------------------------------
jest.mock('node-fetch');
const fetch = require('node-fetch');
const {Response} = jest.requireActual('node-fetch');
beforeEach(() => {
jest.clearAllMocks()
})
it('should call with valid url', async () => {
const pair = 'EURUSD';
fetch.mockReturnValue(Promise.resolve(new Response({})));
await ccyPairIsValid(pair);
expect(fetch).toHaveBeenCalled();
expect(fetch.mock.calls[0][0]).toHaveBeenCalledWith(process.env.PATH + '/check');
})
Error: expect(received).toHaveBeenCalledWith(...expected)
Matcher error: received value must be a mock or spy function
Received has type: string
Received has value: "http://localhost:8000/check"

You are calling fetch with two arguments, if you don’t care about your requestOptions argument then you can use expect.anything()

Related

Unit Test for AWS RedshiftData on node.js using jest

I am new to AWS Redshift Data. I was trying to write a jest unit test cases for AWS Redshift Data. I used aws-sdk for AWS Redshift Data and aws-sdk-mock to mock it and have a static response (success and error), But aws-sdk-mock seems not working to return mock response.
Here's my redshift-data.service.js:
const AWS = require('aws-sdk');
const rsd = new AWS.RedshiftData();
const logger = require('../config/logger');
const getDescribeStatement = async (queryId) => {
try {
return rsd
.describeStatement({ Id: queryId })
.promise()
.then((response) => {
return response;
})
.catch((error) => {
logger.info('DescribeStatement has failed.');
throw new Error(error);
});
} catch (error) {
logger.error(`Redshift error: ${error}`);
return { status: 'fail', error: error.message };
}
};
module.exports = {
getDescribeStatement,
};
and Here's my redshift-data.service.test.js:
const awsMock = require('aws-sdk-mock');
const redshiftDataService = require('../../../src/services/redshift-data.service');
describe('Redshift Data Service', () => {
it('should be able to describe statement/query', async () => {
awsMock.mock('RedshiftData', 'describeStatement.promise()', jest.fn().mockReturnValue(Promise.resolve(true)));
awsMock.describeStatement = jest.fn().mockReturnValue(Promise.resolve(true));
const queryId = 'd7a21d3b-5833-4793-a896-e430fb729f7b';
const service = await redshiftDataService.getDescribeStatement(queryId);
expect(service).toBeTruthy();
});
it('should not be able to describe statement/query', async () => {
awsMock.mock('RedshiftData', 'describeStatement.promise()', jest.fn().mockReturnValue(Promise.resolve(false)));
awsMock.describeStatement = jest.fn().mockReturnValue(Promise.resolve(false));
const queryId = 'd7a21d3b-5833-4793-a896-e430fb729f7b';
const service = await redshiftDataService.getDescribeStatement(queryId);
expect(service).toBeFalsy();
});
});
Thanks in advance for helping.

React native async function returns empty object

I am trying to get a token stored in securestore, and pass it to url. When I try to call the api the value of the token is just an empty object. I am able to see the value t here if I alert in readToken function. Its not passed to getMovies function.
const readToken = async () => {
try {
const storedToken = await SecureStore.getItemAsync('token');
return storedToken;
} catch (e) {
console.log(e);
}
};
const getMovies = async () => {
try {
let url = 'https://someurl.de/api/getschichten/?userid=9&token='+readToken();
alert(url);
const response = await fetch(url);
const json = await response.json();
setData(json);
} catch (error) {
console.error(error);
} finally {
setLoading(false);
}
}
So, I changed my code according to kipnodels. Here's my code that works
let myToken = await readToken();
let url = 'https://esm.nvii-dev.de/api/getschichten/?userid=9&token='+myToken;

Why is this not working? Testing non exported-function with Rewire / Jest

Pretty much running the exact same code elsewhere however, this time, I am using rewire to test a non-exported function at helper.js.
When debugging the following I get to return await db.collection('foo') which returns undefined and throwing when attempting 'undefined.findOne()' naturally. My understanding is that db.collection('foo') should return mockDbConnect in this case allowing to chain findOne, which it is not doing...
Help is appreciated.
foo.test.js
const rewire = require('rewire');
const helper = rewire('../../../src/models/helper/helpers');
describe('model helpers', () => {
describe('searchValue', () => {
it('should return an instance', async () => {
const searchValue = helper.__get__('searchValue')
const mockFoo = { foo: '1' }
const fooId = '1';
const mockDbConnect = {
collection: jest.fn().mockReturnThis(),
findOne: jest.fn().mockReturnValue(mockFoo)
}
try {
const res = await searchValue(fooId, mockDbConnect);
expect(mockDbConnect.collection).toHaveBeenCalledWith('foos');
} catch (err) {
throw err;
}
});
})
})
helpers.js
const searchValue = async (fooId, db) => {
return await db
.collection('foos')
.findOne({ fooId: fooId });
};

Internal server error aws lambda function nodejs

I am trying out a demo with AWS lambda function using Axios and Cheerio, I am getting back response after calling the endpoint as {message: Internal Server Error}
exports.lambdaHandler = async (event, context) => {
try {
const axios = require('axios');
const cheerio = require('cheerio');
axios.get('https://www.kitco.com').then((response) => {
const html = response.data;
const $ = cheerio.load(html);
const ask = $('#AU-ask').text();
const bid = $('#AU-bid').text();
const resbid = bid.slice(0,7);
const resask = ask.slice(0,7);
const result = {
"ask": resask,
"bid": resbid
}
return result;
});
response = {
'statusCode': 200,
'body': result
}
} catch (err) {
console.log(err);
return err;
}
return response
};
result is clearly not in response scope, therefore this will result in a typical undefined error.
The solution would be to handle the logic inside axios.get callback, try this:
const axios = require('axios');
const cheerio = require('cheerio');
exports.lambdaHandler = (event, context) => {
axios.get('https://www.kitco.com')
.then((response) => {
const html = response.data;
const $ = cheerio.load(html);
const ask = $('#AU-ask').text();
const bid = $('#AU-bid').text();
const resbid = bid.slice(0, 7);
const resask = ask.slice(0, 7);
const result = {
statusCode: 200,
body: {
ask: resask,
bid: resbid
}
};
console.log(result);
})
.catch(err => {
console.log(err);
});
};
You can get error detail in monitor tab of Lambda console web. I guest you get back an error like response is undefined in return response line.
With your code, return response line will be execute immediately when you call the function, but response did not defined in the lambdaHandler scope.
I recommended that, don’t mix async/await syntax with Promise syntax (.then .catch), just use one of them, I suggest use async/await syntax.
The function will like:
exports.lambdaHandler = async (event, context) => {
try {
const axios = require('axios');
const cheerio = require('cheerio');
const response = await axios.get('https://www.kitco.com'); // wait until we get the response
const html = response.data;
const $ = cheerio.load(html);
const ask = $('#AU-ask').text();
const bid = $('#AU-bid').text();
const resbid = bid.slice(0, 7);
const resask = ask.slice(0, 7);
const result = {
"ask": resask,
"bid": resbid
}
return {
statusCode: 200,
body: JSON.stringify(result), // If you working with lambda-proxy-integrations, the `body` must be a string
}; // return to response the request
} catch (err) {
console.log(err);
return {
statusCode: 500, // Example, http status will be 500 when you got an exception
body: JSON.stringify({error: err}),
}
}
};

Capturing errors with Async/Await

I have a part of my code that makes several API calls to different endpoints and I want to know if any of those calls fail so I can display an appropriate error message. Right now, if an error happens in one() it will stop all other calls from happening, but that's not what I want; If an error occurs, I want it to populate the errors object and have the program continue on.
async function gatherData() {
let errors = { one: null, two: null, three: null };
const responseOne = await one(errors);
const responseTwo = await two(errors);
const responseThree = await three(errors);
if (!_.isNil(errors.one) || !_.isNil(errors.two) || !_.isNil(errors.three)) {
// an error exists, do something with it
} else {
// data is good, do things with responses
}
}
gatherData();
async function one(errors) {
await axios
.get("https://jsonplaceholder.typicode.com/comment")
.then(res => {
return res;
})
.catch(err => {
errors.one = err;
return err;
});
}
async function two(errors) {
await axios
.get("https://jsonplaceholder.typicode.com/comments")
.then(res => {
return res;
})
.catch(err => {
errors.two = err;
return err;
});
}
async function three(errors) {
await axios
.get("https://jsonplaceholder.typicode.com/comments")
.then(res => {
return res;
})
.catch(err => {
errors.three = err;
return err;
});
}
If you pass the errors to the async functions, so pass the errors object as parameter
const responseOne = await one(errors);
const responseTwo = await two(errors);
const responseThree = await three(errors);

Categories

Resources