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
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
}
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)
}
}
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);
}
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()
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!");
}
}