I've got a controller which I'm using the 'next' parameter, and I have no idea how to include it into the test. I've done request and response, everything is ok, but when I use the next, I've got the error asking for the 3rd argument. How to test 'next' in this case?
error
Expected 3 arguments, but got 2.ts(2554)
car.controller.ts(20, 5): An argument for 'next' was not provided.
controller test
describe('Cars Controller Tests', () => {
const carModel = new CarModel();
const carService = new CarService(carModel);
const carController = new CarController(carService);
const req = {} as Request;
const res = {} as Response;
before(async () => {
sinon.stub(carService, 'create').resolves(mock.carMockWithId);
res.status = sinon.stub().returns(res);
res.json = sinon.stub().returns(res);
});
after(()=>{
sinon.restore();
})
it('1 - CREATE runs successfully', async () => {
req.body = mock.carMock;
await carController.create(req, res);
expect((res.status as unknown as sinon.SinonStub).calledWith(201)).to.be.true;
expect((res.json as sinon.SinonStub).calledWith(mock.carMockWithId)).to.be.true;
});
});
I just got from an article I found:
declare Next then test as usual:
const req = {} as Request;
const res = {} as Response;
const next = {} as NextFunction;
....
await carController.create(req, res, next);
Related
I'm having situation where I want to write unit test cases for a function to make sure if it is working fine or not. So I have created stub for that specific function and when I tries to calls fake that stub, the function is actually getting called instead of fake call. Below is my scenario:
I have an main function from where I'm calling the function saveData(**).
saveData(**) function is calling AWS SQS to save an message to DB
Below is my main function:
'use strict';
async function mainFunction() {
try {
await saveData(
name,
age,
);
return true;
} catch (e) {
console.log('Error - [%s]', e);
return null;
}
}
module.exports = { mainFunction };
Below is my saveData(**) function:
'use strict';
const AWS = require('aws-sdk');
const sqs = new AWS.SQS();
const saveData = async (
name,
age,
) => {
await sendMessage(JSON.stringify(dbData));
const params = {
DelaySeconds: <some_delay>,
MessageAttributes: <messageAttributes>,
MessageBody: {name:name, age:age},
QueueUrl: <URL_FOR_QUEUE>,
};
return sqs.sendMessage(params).promise();
return true;
};
module.exports = {
saveData,
};
And my test case is,
'use strict';
const express = require('express');
const bodyParser = require('body-parser');
require('app-module-path').addPath('./src');
const sinon = require('sinon');
const app = express();
const sqsSender = require('lib/queue');
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
const main = require('../../../src/main-function');
const routes = require('routes');
routes.configure(app);
let mainFunctionStub;
let saveDataStub;
describe('/v1/main', () => {
beforeEach(() => {
mainFunctionStub = sinon.stub(main, 'mainFunction');
saveDataStub = sinon.stub(sqsSender, 'saveData');
});
describe('Test', () => {
it(`should return success`, (done) => {
const name = 'Name';
const age = 'Age';
saveDataStub.resolves({
name,
age,
});
});
});
afterEach(() => {
mainFunctionStub.restore();
mainFunctionStub.reset();
saveDataStub.restore();
saveDataStub.reset();
});
});
But this test is returning,
error: Jun-20-2021 20:07:05: Error - [Error [ConfigError]: Missing region in config
and,
Error: Timeout of 3500ms exceeded.
From this error I can say that this is actually calling SQS function instead of faking. How can I resolve this or how can I fake call to this function? I'm new to this unit testing so any help would be appriciated.
Stubbing works by replacing the property on the exports object. Since the require happens before sinon replaces the function, you capture the reference to the original function instead of dynamically using the currently set one.
You haven't showed your require calls in the main file, but from the call-site I infer you're importing it like const { saveData } = require('../foo/sqsSender'). This means you're grabbing the function off of the object when first loading the code. If you instead keep a reference to the sqsSender module instead, and reference the function on invocation, the stub should work.
'use strict';
// Don't destructure / grab the function.
const sqsSender = require("../foo/sqsSender")+
async function mainFunction() {
try {
// Use reference through module
await sqsSender.saveData(
name,
age,
);
return true;
} catch (e) {
console.log('Error - [%s]', e);
return null;
}
}
module.exports = { mainFunction };
I am new to using Jest for unit tests. How can I mock this simple http request method "getData"? Here is the class:
const got = require("got")
class Checker {
constructor() {
this.url
this.logData = this.logData.bind(this);
this.getData = this.getData.bind(this);
}
async getData(url) {
const response = await got(url);
const data = await response.body;
return data;
}
async logData(first, second, threshold) {
let data = await this.getData(this.url)
console.log("received " + data.body);
}
}
I am trying to mock "getData" so I can write a unit test for "logData". Do I need to mock out the entire "got" module? Thanks.
If you change invoking got to got.get you should be able to have a working test like so:
const got = require('got');
const Checker = require('../index.js');
describe("some test", () => {
beforeEach(() => {
jest.spyOn(got, 'get').mockResolvedValue({ response: { body: { somekey: "somevalue" } } } );
});
it("works", async () => {
new Checker().getData();
expect(got.get).toBeCalledTimes(1);
})
})
One approach is to use dependency injection. Instead of calling 'got' directly, you can 'ask for it' in the class constructor and assign it to a private variable. Then, in the unit test, pass a mock version instead which will return what you want it to.
const got = require("got");
class Checker {
constructor(gotService) {
this.got = gotService;
this.logData = this.logData.bind(this);
this.getData = this.getData.bind(this);
}
async getData(url) {
const response = await this.got(url);
const data = await response.body;
return data;
}
async logData(first, second, threshold) {
let data = await this.getData(this.url)
console.log("received " + data.body);
}
}
//real code
const real = new Checker(got);
//unit testable code
const fakeGot = () => Promise.resolve(mockedData);
const fake = new Checker(fakeGot);
Here is what we are doing:
'Inject' got into the class.
In the class, call our injected version instead of directly calling the original version.
When it's time to unit test, pass a fake version which does what you want it to.
You can include this directly inside your test files. Then trigger the test that makes the Http request and this will be provided as the payload.
global.fetch = jest.fn(() =>
Promise.resolve({
json: () => Promise.resolve({ data: { eth: 0.6, btc: 0.02, ada: 1 } }),
})
);
it('should return correct mock token values', async () => {
const addresses = ["mockA", "mockB", "mockC"];
const res = await getTokenData(addresses);
expect(res.data).toEqual({ eth: 0.6, btc: 0.02, ada: 1 });
});
Entrypoint of my server is publisher.js. Its code is the following:
'use strict';
const publishingRoute = require('./routes/enqueue');
. . . .
. . . .
const PublishingServicePort = process.env.PUB_PORT || 4001;
const RabbitMQHostURL = process.env.RABBITMQ_AMQP_URL;
const RabbitMQQueueName = process.env.QUEUE;
const RabbitMQRoutingKey = process.env.ROUTING_KEY;
const RabbitMQExchange = process.env.EXCHANGE;
let rbmqChannel;
let rbmqConnection;
const app = express();
app.use(bodyParser.json());
//initConnection() creates the TCP connection and confirm channel with the Broker. No error here
(async function initConnection() {
rbmqConnection = await rbmqConnectionManager.connect(amqp, RabbitMQHostURL);
rbmqChannel = await rbmqConnectionManager.createConfirmChannel(rbmqConnection);
})();
//Error Here: None of the parameter is passed to the callback function
app.use('/enqueue', publishingRoute.enqueueUser(rbmqChannel, RabbitMQQueueName, RabbitMQRoutingKey, RabbitMQExchange));
app.listen(PublishingServerPort , async () => {
console.log(`Server listening on ${PublishingServerPort }`);
})
../routes/ contains modules, that handles the routes from the publisher.js. One of the routes's module is the enqueue.js. It enqueues JabberID of the users (JSON) into the RabbitMQ queue, through the Exchange. The following code are of enqueue.js module.
'use strict';
const router = require('express').Router();
const PublisherService = require('../services/rbmq-publisher');
export function enqueueUser(amqpChannel, queueName, routingKey, exchange) {
//Error: No parameter has reached here. amqpChannel, queueName, routingKey, and exchange are undefined. I need all of them here.
router.post('/', async (req, res) => {
const content = req.body.payload;
await PublisherService.PublishPayload(amqpChannel, exchange, routingKey, content);
res.status(200);
res.send({
"Message": "OK",
"payloadEnqueued": content
});
});
return router;
}
rbmq-publisher.js is the controller (module) for handling publishing/enqueuing into the RabbitMQ Exchange. The following code is of the rbmq-publisher.js
'use strict';
const PublishPayload = async function(channel, exchange, routingKey, content) {
//Error: None of the parameter has reached here. All of them are undefined.
console.info(`[AMQP] : Publishing Message ...`);
try {
await channel.publish(exchange, routingKey, Buffer.from(JSON.stringify(content)));
console.log(`[AMQP SUCCESS]: JabberID Published`);
}
catch(exception) {
//This is what is being shown in the console window. I have written the error below this code snippet
console.error(`[AMQP ERROR]: ${exception}`);
}
};
export {
PublishPayload
};
Console windows shows the following error:
[AMQP ERROR]: TypeError: Cannot read property 'publish' of undefined
None of the arguments from the app.use() has reached the callback function. Where did I go wrong?
I have added simple git branch function related code in getgitbranches.js file.
Calling this method from index.js.
Facing difficulty in returning branch summary data to index.js file.
index.js
app.get('/GetGitBranches', (req, res) => {
var gitBranches
console.log('inside')
gitBranches = require('./getgitbranches.js')
console.log(gitBranches.showlog(req,res))
res.send(gitBranches.showlog(req,res))
}
getgitbranches.js
let branchSummary = {}
exports.showlog = function (req, res){
const gitVariable= require('simple-git/promise')()
var branchVariable=gitVariable.branch(['-r']);
branchVariable.then(function (data) {
branchSummary.result = data.all
giveback(data.all)
})
}
giveback = function (data){
//console.log("givaback"+data)
branchSummary.result =data;
console.log("Branch Summary Result"+ branchSummary.result)
return branchSummary.result;
}
You are trying to log the value which is resolved inside the promise you should either await untill the promise is resolved or use callback
index.js
app.get('/GetGitBranches', async (req, res) => {
var gitBranches
console.log('inside')
gitBranches = require('./getgitbranches.js')
const response = await gitBranches.showlog(req,res)
return res.send(response)
}
getGitBranches.js
let branchSummary = {}
exports.showlog = async function (req, res){
const gitVariable= require('simple-git/promise')()
const result = await gitVariable.branch(['-r']);
return giveback(result.all);
}
giveback = function (data){
//console.log("givaback"+data)
branchSummary.result =data;
console.log("Branch Summary Result"+ branchSummary.result)
return branchSummary.result;
}
I am trying to access Tron smart contract which is deployed on the Shasta test network using Tron-Web. I am using node-casiko server Following is my code:
const TronWeb = require('tronweb')
// This provider is optional, you can just use a url for the nodes instead
const HttpProvider = TronWeb.providers.HttpProvider;
const fullNode = 'https://api.shasta.trongrid.io';
const solidityNode = 'https://api.shasta.trongrid.io';
const eventServer = 'https://api.shasta.trongrid.io';
const privateKey = 'my test account private key';
const tronWeb = new TronWeb(
fullNode,
solidityNode,
eventServer,
privateKey
);
module.exports = {
tmp: async function (req, res, next){
try{
var contract = await tronWeb.trx.getContract("TS71i14jzLawbtu4qPDKEsFERSp6CQb93948");
//res.send(contract)
var result = await contract.test().call();
//res.send(result);
}
catch(err){
console.error(err)
}
}
}
When I execute this js file using node having version v10.15.3. I am getting Error as:
TypeError: contract.test is not a function
at tmp (/home/administrator/node-Casiko/models/tronContract.js:25:32)
at process._tickCallback (internal/process/next_tick.js:68:7)
If I print the contract variable it is printing all information about the contract, but it is not calling the contract methods. Can somebody help me with this problem?
Well, I managed to find an answer for self-question. Just change the code as below. It works!!
module.exports = {
tmp: async function (req, res, next){
try{
var contract = await tronWeb.contract()
.at("TS71i14jzLawbtu4qPDKEsFERSp6CQb93948")
var result = await contract.test().call();
}
catch(err){
console.error(err)
}
}