How to stub AWSXray.captureHTTPsGlobal using Sinon? - node.js

In my nodejs lambda function I use AWSXray to simply capture https calls made by the function.
const AWSXRay = require("aws-xray-sdk-core");
AWSXRay.captureHTTPsGlobal(require("https"));
In my unit tests how do I mock this?
I have tried mocking it with sinon by:
before(async () =>
await sandbox.stub(AWSXRay, 'captureHTTPsGlobal').returns({})
);
after(async () => {
await sandbox.restore();
});
Getting error in test as:
OperationalError: Failed to get the current sub/segment from the context.
at Object.contextMissingRuntimeError [as contextMissing]

The problem was not with Xray, but the way I was writing the tests.
AWSXray will try to capture all https calls. But this scenario should ideally not arise in tests because in an ideal test suite all http/https calls anyway should be stubbed.
I solved the problem by properly mocking the units where https calls were being made.

Related

Test using mongodb-memory-server is failing/timing out

I’m setting up mongodb-memory-server in my backend for test purposes and am experiencing some issues when running tests that I need to debug. My issue is that when I run my test (which will create a mongodb doc somewhere in the service being tested), the test times out.
As I understand it, this is because when the test is executed and a new mongo doc is trying to be created during the test, I console log mongoose.connection.readyState and it says it’s 0, meaning that mongoose is disconnected. This is strange to me because I added console logs to my connectMongoose() function (pictured below) and it says that mongoose is connected.
So my main question is why does it say mongoose is connected at the end of connectMongoose(), but it says it’s disconnected during the execution of the unit test/service function? How can I ensure that MongoDB-memory-server is fully connected prior to test execution?
Below is a screenshot showing how I am doing the mongoose test connection:
Below this is a screenshot of exactly where and how mongodb-memory-server is being used:
Here is a screenshot of my jest.config.js:
And finally the actual test file which has the failing test (what I’m asking about):
beforeAll(connectMongoose)
beforeEach(clearDatabase)
afterAll(disconnectMongoose)
Your three functions here are async functions, but you don't await them - is it possible that the connect Mongoose returns whilst the promise is still awaiting, and the other code continues despite the async function not having completed yet?
Perhaps this would better serve your purpose?
beforeAll(() => {
await connectMongoose
})
Before :
beforeAll(connectMongoose)
beforeEach(clearDatabase)
afterAll(disconnectMongoose)
After:
beforeAll(async() => {await connectMongoose})
beforeEach(async() => {await clearDatabase})
afterAll(async () => { await disconnectMongoose})
The reason is you should wait until the mongoose connection is done completely and remove
set timeout in connectMongoose function not needed there.If you want to use jest timeout you can use it in the beforeEach function.

How to check rabbit connection in node js for unit test using mocha and chi

I'm using amqplib-package for connecting to RabbitMQ in nodeJS and want to know
how I can check/verify my RabbitMQ-connection using Mocha and Chai in nodeJS?
You can try one of the following:
you can create a valid rabbit-mq connection using a docker iamage docker-rabbitmq and make real requests to your application but this is not unit testing, but more like integration testing.
You can mock it using sinon a very good article I can suggest on this topic is Best practices for spies, stubs, and mocks in sinonjs
You can follow this topic on google groups NodeJS + RabbitMQ (amqplib): How to write good Unit Test against them.
If you are using ampqlib package and you want to test whether the connection is established or not then it is not considered as a unit test, we can call it an integration test.
Other answers have good content about integration testing, but for unit testing you can use amqplib-mocks (https://www.npmjs.com/package/amqplib-mocks) which is a simple mocking framework for amqplib.
For a basic unit test you can check if amqp.connect(url) is called and expect the URL you want.
I can also show a basic example how you can get a stubbed connection object:
(ps: This is not a running code, this is just for reference)
subscriber.js
const amqp = require('amqplib');
class Subscriber {
async getConnection(url) {
const connection = await amqp.connect(url);
return connection;
}
}
Subscriber class has a method getConnection which establishes and return a connection object with rabbitmq.
subscriber.test.js
const amqpMock = require('amqplib-mocks');
const sinon = require('sinon');
const mockConnection = await amqpMock.connect('mockurl.com');
const getConnectionStub = sinon.stub(Subscriber.prototype, 'getConnection').returns(mockConnection);
In above code you can either stub ampq.connect directly or stub getConnection method and return a connection object as returned by amqp-mock's connect method.
To know more about sinon used above, click.

Verify hapi server.log is being called with expected message

I have a requirement to verify that certain actions are being logged to the server and would like to know why I'm having trouble stubbing the call to hapi server.log().
In my unit tests I instantiate a hapi server using:
const Hapi = require('hapi');
const server = new Hapi.Server();
I have my stub setup as:
const Sinon = require('sinon');
const logStub = Sinon.stub(server, 'log');
I am using server.inject to call the endpoint that I expect to call server.log. When I debug the test, I have a breakpoint set to verify that server.log is being called in my endpoint and I have a breakpoint in my unit test to verify that the logStub is being called. However, when I call this:
server.inject(localRequest).then(() => {
const spyCall = logStub.getCall(0);
})
spyCall is null and if I inspect logStub, called is false and the callCount is 0, despite server.log being called in my endpoint.
What am I missing here? Does calling server.inject cause an issue with stubbing methods on the hapi server?
The best solution I have been able to find is to use the server.once method on the hapi server.
I neglected to mention in my question that I'm using hapi version 16.6.2 so this solution may not work for the latest version of hapi as it is much different.
server.once({
name: 'log',
filter: 'myTag',
}, (update) => {
Code.expect(update.data).to.equal('expectedMessage');
});
Using this approach allowed me to specify the event 'log' and the specific tag (or tags) for my log event. Hope this helps someone else!

Mocking http requests in node using mocha and sinon

I have written a NodeJS app using express that proxies some calls to external APIs. So I am trying to write a unit test using Mocha and Sinon. My goal is to test the app without any internet connectivity so I am trying to mock the https requests and return mock replies.
I'm having a problem that I can't find any examples or tutorials that fit my case. My node app listens on port 8081 for http requests and then proxies them to another site. I want to test my app without it having to actually send the request to those external servers. I'm trying it below and I put the json replies I want to send back in the server.respondsWith() function.
Am I doing this the right way by making an ajax call with chai? or should I be sending the requests inside my app somehow. Any help is appreciated.
var assert = require('assert');
var chai = require('chai');
var spies = require('chai-spies');
var chaiHttp = require('chai-http');
var https = require('https');
var should = chai.should();
var expect = chai.expect;
var sinon = require('sinon');
chai.use(spies);
chai.use(chaiHttp);
describe('Car Repository', function() {
var server;
before(function() {
server = sinon.fakeServer.create();
});
after(function() {
server.restore();
});
var url = 'http://127.0.0.1:8081';
it('should succeed and return a list of cars', function(done) {
server.respondWith('POST', 'https://api.sandbox.cars.com/v2/token_endpoint', JSON.stringify({"access_token":"1t3E4IykfpJAbuFsdfM2oFAo5raB5vhfOV0hAYe","token_type":"bearer","expires_in":604800}));
server.respondWith('GET', url+'/cars', JSON.stringify({'test':'this works'}));
chai.request(url)
.get('/cars')
.end(function(err, res) {
if (err) {
throw err;
}
res.should.have.status(200);
res.body.should.have.property('test');
console.log(res.body);
done();
});
});
});
Check out the Nock library. It does exactly what you're looking for.
Nock is an HTTP mocking and expectations library for Node.js
Nock can be used to test modules that perform HTTP requests in isolation.
For instance, if a module performs HTTP requests to a CouchDB server or makes HTTP requests to the Amazon API, you can test that module in isolation.
The new solution here is sinon's fake server:
http://sinonjs.org/releases/v2.1.0/fake-xhr-and-server/#fake-server
Take a look at node-tdd and the useNock flag. It builds on top of mocha and nock (mentioned in the accepted answer) and automatically creates and uses a recording file for each test.
We love that it's so easy to use. Basically just "enable and forget" and focus on writing requests / test cases. If requests for a test change, one still needs to delete or adjust the recording file, but at least it's entirely separate from the code.

what api is this test written in?

code snippet:
describe('GetList', () => {
it('should respond with 200 Success', function* () {
let res = yield api
.get(apiPath)
.set({ })
.expect(200)
.endAsync();
res.body.forEach((item) => {
item.should.have.property('appName');
item.should.have.property('appDomain');
});
I need to write tests in the framework in which the above code is written.
if you can hint what framework it is, maybe I can read api docs and write one myself.
what I have to do is write a test that compares two arrays returned from api calls.
from npm settings it seems it use mocha and istanbul as testing framework.
That looks like Jasmine Behavior-Driven JavaScript.
Perhaps it's Mochajs as it has should.have. Jasmine, at least on the 2.4 documentation doesn't mention the should.have API.
Could you see what's included when this test is executed? Or the package.json file. Likely at the devDependencies.

Resources