Unit Test for AWS RedshiftData on node.js using jest - javascript

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.

Related

How to Wait Until a MongoDB Connection is Made before Using the Database

I have the following code to create a connection to my MongoDB database, and to store it for future use.
const mongodb = require('mongodb');
const MongoClient = mongodb.MongoClient;
// The database will be defined once a connection to between the cluster and mongodb is created
let _database;
const uri = '';
const databaseName = 'db';
const mongoConnect = () => {
MongoClient.connect(uri)
.then((client) => {
_database = client.db(databaseName);
})
.catch((err) => {
console.log(err);
throw err;
});
};
const getDb = () => {
if (_database) {
return _database;
}
throw 'No database found!';
};
module.exports = {
mongoConnect,
getDb
}
My problem is that _database is undefined until the connection is made. If my website tries to use the database before _database is defined it will throw an error and crash.
I want to make it so instead of crashing, other portions of my code would just wait until _database is not undefined. Sounds like a await/async solution is needed, but I can't wrap my head around how to approach implementing something like that here. Any advice would be great!
First approach: To make mongoConnect an async function and await on it before any of the remaining code is executed.
const mongoConnect = async () => {
try {
const client = await MongoClient.connect(uri);
_database = client.db(databaseName);
} catch(e) {
console.log(err);
throw err;
}
};
In the beginning of your code
await mongoConnect();
//Remaning code here
Second approach: To make getDb function await till database connection is available
const mongodb = require('mongodb');
const MongoClient = mongodb.MongoClient;
const uri = '';
const databaseName = 'db';
const databasePromise = new Promise((resolve, reject) => {
MongoClient.connect(uri)
.then((client) => {
resolve(client.db(databaseName));
})
.catch((err) => {
reject(err);
});
})
const getDb = async () => {
return await databasePromise;
};
module.exports = {
getDb
}
Sample code for you to run and check the second approach:
const databasePromise = new Promise((resolve) => {
console.log("Connecting to db in 5 seconds...")
setTimeout(() => {
console.log("Done")
resolve("done")
}, 5000)
})
const getDb = async () => {
return await databasePromise;
};
console.time("First_getDb_call")
getDb().then(res => {
console.timeEnd("First_getDb_call")
console.log(res)
console.time("Second_getDb_call")
getDb().then(res => {
console.timeEnd("Second_getDb_call")
console.log(res)
})
})
**Pretty Simple approach ** Just add await before MongoClient.connect function and make function async Now It will wait for the connection to have response then move forward.
const mongodb = require('mongodb');
const MongoClient = mongodb.MongoClient;
// The database will be defined once a connection to between the cluster
and mongodb is created
let _database;
const uri = 'mongodb://localhost:27017/mydb';
const databaseName = 'db';
const mongoConnect = async () => {
await MongoClient.connect(uri)
.then((client) => {
_database = client.db(databaseName);
})
.catch((err) => {
console.log(err);
throw err;
});
};
const getDb = () => {
if (_database) {
return _database;
}
throw 'No database found!';
};
module.exports = {
mongoConnect,
getDb
}

nodejs javascript promise resolve

I can't seem to figure out how to save the results of SomeQuery promise. Essentially I would like to take the value in res and pipe it into parseQuery function and return the final results. How do I make the parsed result accessible to an APIs response.
const neo4j = require('neo4j-driver')
var parser = require('parse-neo4j')
const astria_queries = require('./astriaQueries')
const uri = 'bolt://astria_graph:7687'
const user = 'xxx'
const password = 'xxx'
const someQuery = (query) => {
// run statement in a transaction
const driver = neo4j.driver(uri, neo4j.auth.basic(user, password))
const session = driver.session({ defaultAccessMode: neo4j.session.READ })
const tx = session.beginTransaction()
tx.run(query)
.then((res) => {
// Everything is OK, the transaction will be committed
parseQuery(res)
})
.then(() => {
// Everything is OK, the transaction will be committed
})
.catch((e) => {
// The transaction will be rolled back, now handle the error.
console.log(e)
})
.finally(() => {
session.close()
driver.close()
})
}
const parseQuery = (result) => {
try {
const test = parser.parse(result)
console.log(test)
} catch (err) {
console.log(err)
}
}
module.exports = {
someQuery,
}
It finally clicked with me. Here is the solution I came up with. Hopefully it will help others. If there is a better way please let me know. Thank you #fbiville for you help.
async actions
const neo4j = require('neo4j-driver')
var parser = require('parse-neo4j')
const astria_queries = require('./astriaQueries')
const uri = 'bolt://astria_graph:7687'
const user = 'neo4j'
const password = 'neo'
async function getRecords(query) {
// run statement in a transaction
const driver = neo4j.driver(uri, neo4j.auth.basic(user, password))
const session = driver.session({ defaultAccessMode: neo4j.session.READ })
const tx = session.beginTransaction()
try {
const records = await tx.run(query)
const parseRecords = await parseQuery(records)
return parseRecords
} catch (error) {
console.log(error)
} finally {
session.close()
driver.close()
}
}
async function parseQuery(result) {
try {
const parsedRes = await parser.parse(result)
// console.log(parsedRes)
return parsedRes
} catch (err) {
console.log(err)
}
}
// getRecords(astria_queries.get_data_sources)
module.exports = {
getRecords,
}
api send()
exports.get_data_sources = async (req, res) => {
try {
queryFuns.getRecords(astria_queries.get_data_sources).then((response) => {
res.send(response)
})
} catch (error) {
res.status(500).send(error)
console.log(error)
}
}

how to add ".then()" and ".catch()" to a lambda in javascript

I'm looking for making something like this in function. The problem with this example is the .then() statement from then on. (syntax problem). How would I do issue the lambda with a "then" and "catch" sections?
const AWS = require("aws-sdk");
const lambda = new AWS.Lambda({
region: "us-west-2"
});
exports.my_func = async function(email) {
const params = {
FunctionName: funcion_name,
InvocationType: 'RequestResponse',
LogType: 'Tail',
Payload: JSON.stringify(email)
};
lambda.invoke(params)
.then(response => {
const thing = other_function(response)
return thing
})
.catch(err => {
throw my_error(400, 'Not working '+ err);
})
}
You could use .promise()
const lambdaInvokePromise = params => lambda.invoke(params).promise()
// ...
lambdaInvokePromise(params)
.then(response => {
const thing = other_function(response)
return thing
})
.catch(err => {
throw my_error(400, 'Not working ' + err)
})
const AWS = require('aws-sdk')
const lambda = new AWS.Lambda({
region: 'us-west-2'
})
const lambdaInvokePromise = params => lambda.invoke(params).promise()
exports.my_func = async function(email) {
const params = {
FunctionName: funcion_name,
InvocationType: 'RequestResponse',
LogType: 'Tail',
Payload: JSON.stringify(email)
}
lambdaInvokePromise(params)
.then(response => {
const thing = other_function(response)
return thing
})
.catch(err => {
throw my_error(400, 'Not working ' + err)
})
}
Reference
Using Javascript Promise - AWS SDK for Javascript
You don't need to use then/catch. You can use promise as already mentioned by #hgb123, but I would change the code slightly to use async/await since you're already in an async function.
try {
const response = await lambda.invoke(params).promise();
return other_function(response)
} catch(e) {
throw my_error(400, 'Not working '+ err);
}

Issue unit testing this function in node with node-fetch

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()

Error acessing mongo collection using mongo client asynchronously

I've built the following mongo client access bootstrap file:
import { MongoClient } from "mongodb";
let db = null;
// Connect to mongo
const uri = "mongodb://localhost/mydb";
const opts = { useUnifiedTopology: true };
const connect = async () => {
console.log("Connecting to database...");
let client = await MongoClient.connect(uri, opts).catch(error => {
console.log("Error connecting to database: " + err);
});
if (client) {
console.log("Database connected.");
db = client.db("mydb");
}
return client;
};
// Get database connection
const getDb = async () => {
if (!db) await connect();
return db;
};
// Get Collection
const getCollection = async name => {
let database = await getDb();
let collection = await database.collection(name);
if (!collection)
throw new Error("(mongo) Cannot get collection named " + name);
return collection;
};
export { db, getCollection };
When trying to acess the collection for the first time in another program:
import { getCollection } from "./mongoutils";
const init = async () => {
let user = await getCollection("users").findOne({ name: "Josh"});
console.log("User found!");
}
I'm getting the following error:
UnhandledPromiseRejectionWarning: TypeError: (0 , _mongo.getCollection)(...).findOne is not a function
How can I properly fix this error, keeping the whole structure async/await?
An async function returns a promise and not the resolved data.
Here getCollection() is an async function. So, calling getCollection("users") would return a promise and not the resolved collection itself as I presume what you are expecting. The correct way to do is:
import { getCollection } from "./mongoutils";
const init = async () => {
let userCollection = await getCollection("users");
try {
let user = await userCollection.findOne({ name: "Josh"})
console.log("User found!");
} catch (e) {
console.log("User not found!");
}
}

Categories

Resources