how to clear global var between tests in nodejs? - node.js

I have 2 tests which each one them pass but when i run them together the second test fails.
I have this global var (CURR_GUID) which i want to clear between the tests but i am not sure how to do that.
Since it is not cleared between the tests , its value is still "1111111" and not null.
Any idea?
Class W
"use strict";
var CURR_GUID = null;
class W {
constructor() {
console.log("W ctor")
}
async getDataFromDb() {
if (CURR_GUID) {
return CURR_GUID;
} else {
this.db = require("./Connection").getDb();
console.log("W getDataFromDb")
let res = null;
res = await this.db.one("SELECT guid FROM table", ["NONE"]);
return res.guid;
}
}
async saveGuid(guid) {
this.db = require("./Connection").getDb();
await this.db.none("update table set guid=$1", [guid]);
CURR_GUID = guid;
console.log("currr is" + CURR_GUID);
}
}
module.exports = W;
Class X
"use strict";
const wDao = new (require("../db/W"))();
class X {
async getGuid() {
console.log("X getGuid")
let guid = await wDao.getDataFromDb();
console.log("got guid " + guid);
await wDao.saveGuid(guid);
return guid;
}
}
module.exports = X;
Test.spec.js
const chai = require("chai");
const expect = chai.expect;
const X = require("../src/service/X");
const Connection = require("../src/db/Connection");
const sinon = require("sinon");
describe("component_test", function () {
afterEach(function () {
this.dbStub.restore();
});
it("X_component_test", async function () {
var db = {
one: async () => {
return {
guid: '1111111',
created_on: "123"
}
},
none: async () => {
}
};
this.dbStub = sinon.stub(Connection, "getDb").returns(db);
var dao = new X();
var guid = await dao.getGuid();
expect(guid).to.equal('1111111');
});
it("X_component_test_2", async function () {
var db = {
one: async () => {
return {
guid: '222222',
created_on: "123"
}
},
none: async () => {
}
};
this.dbStub = sinon.stub(Connection, "getDb").returns(db);
var dao = new X();
var guid = await dao.getGuid();
expect(guid).to.equal('222222');
});
});

While it should be possible to achieve the desired result by deleting W and X modules from require.cache in afterEach hook, it might be better to modify the source code a bit so that it can be tested without cache manipulations.
Class W
Turn CURR_GUID variable into an instance property.
"use strict";
class W {
constructor() {
console.log("W ctor");
this.CURR_GUID = null;
}
async getDataFromDb() {
if (this.CURR_GUID) {
return this.CURR_GUID;
} else {
this.db = require("./Connection").getDb();
console.log("W getDataFromDb")
let res = null;
res = await this.db.one("SELECT guid FROM table", ["NONE"]);
return res.guid;
}
}
async saveGuid(guid) {
this.db = require("./Connection").getDb();
await this.db.none("update table set guid=$1", [guid]);
this.CURR_GUID = guid;
console.log("currr is" + this.CURR_GUID);
}
}
module.exports = W;
Class X
Turn wDao from variable into an instance property
"use strict";
const WDao = require("../db/W");
class X {
constructor() {
this.wDao = new WDao();
}
async getGuid() {
console.log("X getGuid")
let guid = await this.wDao.getDataFromDb();
console.log("got guid " + guid);
await this.wDao.saveGuid(guid);
return guid;
}
}
module.exports = X;
In this way every test should work with fresh instances of W and X that do not depend on the closure state.

Related

ZKSync is not a constructor

I am trying to write test using a class , but I am getting an error.
Here is the test:
import assert from 'assert'
const ethers = require('ethers');
const zksync = require('zksync');
const ZKSync = require('../../../../app/scripts/controllers/zksync');
describe('zkSync', function () {
let zkSync
before(async () => {
// zkSync = new ZKSync(new Proxy({}, ethers, zksync))
zkSync = new ZKSync(ethers, zksync);
})
describe('initAccount', function () {
it('registers an account on zksync', async () => {
const TEST_SEED = 'debris dizzy just program just float decrease vacant alarm reduce speak stadium'
const ethersProvider = await new ZKSync.getEthereumProvider(ethers,'rinkeby')
const zkSyncProvider = await new ZKSync.getZkSyncProvider('testnet');
const aliceRinkebyWallet = new ethersProvider.Wallet.fromMnemonic(TEST_SEED);
const aliceZKsyncWallet = new ZKSync.initAccount(aliceRinkebyWallet,zkSyncProvider);
assert.strictEqual(await aliceZKsyncWallet.isSigningKeySet(), true, 'account is registered.')
})
})
})
Here is the code it calls:
const ethers = require('ethers')
const zksync = require('zksync')
export default class ZKSync {
constructor (ethers, zksync) {
// const initState = opts.initState || {}
// this.store = new ObservableStore(initState)
// this.keyringController = opts.keyringController
this.ethers = ethers
this.zksync = zksync
}
async getZkSyncProvider (zksync, networkName) {
let zkSyncProvider
try {
zkSyncProvider = await zksync.getDefaultProvider(networkName)
} catch (error) {
console.log('Unable to connect to zkSync.')
console.log(error)
}
return zkSyncProvider
}
async getEthereumProvider (ethers, networkName) {
let ethersProvider
try {
// eslint-disable-next-line new-cap
ethersProvider = new this.ethers.getDefaultProvider(networkName)
} catch (error) {
console.log('Could not connect to Rinkeby')
console.log(error)
}
return ethersProvider
}
async initAccount (rinkebyWallet, zkSyncProvider) {
const zkSyncWallet = await this.zksync.Wallet.fromEthSigner(rinkebyWallet, zkSyncProvider)
return zkSyncWallet
}
}
I run the tests with mocha test/unit/app/controllers/zksync-lib-test.js.
However , I get the following error:
TypeError: ZKSync is not a constructor
I will appreciate any pointers on this.

ReferenceError: name is not defined

I have a code in Controller
const getLocalDatabaseResule = async (searchURL, reqBody) => {
commonCode(reqBody);
console.log(name);
});
function commonCode(reqBody) {
var name = reqBody.name;
var phone= reqBody.phone;
var email = reqBody.email;
}
Any idea how to add common function in controller
You need to return the body from commonCode
const getLocalDatabaseResule = async (searchURL, reqBody) => {
const {name,phone,email} = commonCode(reqBody);
console.log(name);
};
function commonCode(reqBody) {
const name = reqBody.name;
const phone= reqBody.phone;
const email = reqBody.email;
return {name,phone,email}
}
getLocalDatabaseResule("searchURL", {name:"User",phone:"111", email:"mail#mail.com"})
Also this is possible
const getLocalDatabaseResule = async (searchURL, reqBody) => {
var x = commonCode(reqBody);
console.log(x.name);
});
function commonCode(reqBody) {
this.name = reqBody.name;
this.phone= reqBody.phone;
this.email = reqBody.email;
}

TypeError: dbConn.GetInstance is not a function

I trying to create a common database connection class using typescript for my nodejs express application that returns the MongoDB database object as follows but I always get TypeError: dbConn.GetInstance is not a function
const config = require("config");
const MongoClient = require('mongodb').MongoClient;
export class dbConn {
private db = null;
static url = config.database.uri;
static options = {
bufferMaxEntries: 0,
reconnectTries: 5000,
useNewUrlParser: true,
useUnifiedTopology: true,
};
private constructor() { }
private static instance: dbConn;
public static GetInstance() {//I also tried removing static keyword but still the error remains
if (dbConn.instance == null)
{
dbConn.instance = new dbConn();
}
return dbConn.instance;
}
public getDb() {
if (dbConn.instance.db) {
return dbConn.instance.db;
}
MongoClient.connect(dbConn.url, dbConn.options, function(err: any, db: any){
if(err) {
console.log(err);
return null;
}
dbConn.instance.db = db.db(config.database.name);
return dbConn.instance.db;
});
}
}
Updated 01-Aug-2020
I invoke the above instance from app.ts and my controllers as follows:
app.ts file
const dbConn = require('./utils/db/dbConn');
...//code removed for clarity
const app = express();
const server = http.createServer(app);
...//code removed for clarity
server.listen(port, ()=> {
dbConn.GetInstance().getDb();//I get the error here
console.log('Server running')
});
module.exports = app;
my controller file
getAll = async (pageNumber:any, pageSize:any) : Promise<PageResult<Team>> => {
return new Promise<PageResult<Team>>(async function (resolve, reject){
let result = new PageResult<Team>(pageSize, pageNumber);
var dbo = dbConn.GetInstance().getDb();//same error here too.
var query = {};
var recCount = await dbo.collection("teams").find().count();
if (recCount == 0) {
result.IsSuccessful = true;
result.ReasonForFailure = process.env.NO_RECORDS || "No record(s) to show.";
return resolve(result);
}
if (pageSize == -1) { //-1 means to return all records
dbo.collection("teams")
.find(query)
.sort({ name: 1 })
.toArray(function(err: any, resultSet: any) {
if (err) {
result.IsSuccessful = false;
result.ReasonForFailure = err.message;
return reject(result);
} else {
result.IsSuccessful = true;
result.TotalRecords = recCount;
result.PageNumber = parseInt(pageNumber);
result.PageSize = parseInt(pageSize);
result.Data = resultSet;
return resolve(result);
}
});
} else {
dbo.collection("teams")
.find(query)
.sort({ name: 1 })
.skip((parseInt(pageNumber)-1)*parseInt(pageSize))
.limit(parseInt(pageSize)).toArray(function(err: any, resultSet: any) {
if (err) {
result.IsSuccessful = false;
result.ReasonForFailure = err.message;
return reject(result);
} else {
result.IsSuccessful = true;
result.TotalRecords = recCount;
result.PageNumber = parseInt(pageNumber);
result.PageSize = parseInt(pageSize);
result.Data = resultSet;
return resolve(result);
}
});
}
});
}
Can you please assist what is wrong or what is the missing piece to get this to work?
Thanks,
Hemant.
It seems you're using commonjs as module-resolution strategy. Your import will be the problem in that case. Try changing it to:
const dbConn = require('./utils/db/dbConn').dbConn;
or
const { dbConn } = require('./utils/db/dbConn');
or
import {dbConn } from './utils/db/dbConn';
Here's a simple example to show what's going on. Consider this simple ts-class:
export class TestClass {
static test():void {
console.log("it works")
}
}
It will be transpiled into:
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.TestClass = void 0;
class TestClass {
static test() {
console.log("in workds");
}
}
exports.TestClass = TestClass;
//# sourceMappingURL=index.js.map
If you then require this with const TestClassModule = require('./test-class');, TestClassModule will yield:
{ TestClass: [Function: TestClass] }
Hence, you need to use const { TestClass } = require('./test-class');.

nodejs Cannot stub a singleton in component test

I am trying to stub the getDB function within the Connection class , which is a singleton.
When i am making a unit test on Class B it works fine.
Now i am trying to create a component test, which means using Class A and stub the getDB function again (Class A uses Class B which uses the Connection class - getDb).
But the stubbing doesn't work.
Not sure why.
Here are the classes:
Class Connection
"use strict";
const config = {};
const pgp = require("pg-promise")();
const db = pgp(config);
class Connection {
constructor() {
console.log("Connection ctor")
}
getDb() {
console.log("getDb")
return db;
}
}
module.exports = new Connection();
Class B
"use strict";
class B {
constructor() {
console.log("B ctor")
this.db = require("./Connection").getDb();
}
async getDataFromDb() {
console.log("B getDataFromDb")
let res = null;
res = await this.db.one("SELECT guid FROM table", ["NONE"]);
return res.guid;
}
}
module.exports = B;
Class A
"use strict";
const bDao = new (require("../db/B"))();
class A {
async getGuid() {
console.log("A getGuid")
let guid = await bDao.getDataFromDb();
console.log("got guid " + guid);
return guid;
}
}
module.exports = A;
The Test - the B_unit_test works ,
but when i try to stub the getDb from the connection class, it doesn't stub it and the component_test fails.
const chai = require("chai");
const expect = chai.expect;
const A = require("../src/service/A");
const Connection = require("../src/db/Connection");
const B = require("../src/db/B");
const sinon = require("sinon");
describe("component_test", function () {
before(() => {
var db = {
one: async () => {
return {
guid: '24f475b6-f9fa-495b-83f4-16f6b45b0a6a',
created_on: "123"
}
},
none: async () => {
}
};
this.dbStub = sinon.stub(Connection, "getDb").returns(db);
});
after(() => {
this.dbStub.restore();
});
it("B_unit_test", async function () {
var dao = new B();
var guid = await dao.getDataFromDb();
expect(guid).to.equal('24f475b6-f9fa-495b-83f4-16f6b45b0a6a');
});
it("A_component_test", async function () {
var dao = new A();
var guid = await dao.getGuid();
expect(guid).to.equal('24f475b6-f9fa-495b-83f4-16f6b45b0a6a');
});
});
You'd better stub getDataFromDb of B which is the class that A used directly. The unit test solution:
connection.js:
const config = {};
const pgp = require('pg-promise')();
const db = pgp(config);
class Connection {
constructor() {
console.log('Connection ctor');
}
getDb() {
console.log('getDb');
return db;
}
}
module.exports = new Connection();
b.js:
class B {
constructor() {
console.log('B ctor');
this.db = require('./connection').getDb();
}
async getDataFromDb() {
console.log('B getDataFromDb');
let res = null;
res = await this.db.one('SELECT guid FROM table', ['NONE']);
return res.guid;
}
}
module.exports = B;
b.test.js:
class B {
constructor() {
console.log('B ctor');
this.db = require('./connection').getDb();
}
async getDataFromDb() {
console.log('B getDataFromDb');
let res = null;
res = await this.db.one('SELECT guid FROM table', ['NONE']);
return res.guid;
}
}
module.exports = B;
a.js:
const bDao = new (require('./b'))();
class A {
async getGuid() {
console.log('A getGuid');
let guid = await bDao.getDataFromDb();
console.log('got guid ' + guid);
return guid;
}
}
module.exports = A;
a.test.js:
const B = require('./b');
const sinon = require('sinon');
const { expect } = require('chai');
describe('a', () => {
it('should pass', async () => {
const getDataFromDbStub = sinon.stub(B.prototype, 'getDataFromDb').resolves('24f475b6-f9fa-495b-83f4-16f6b45b0a6a');
const A = require('./a');
const aDao = new A();
const guid = await aDao.getGuid();
expect(guid).to.be.equal('24f475b6-f9fa-495b-83f4-16f6b45b0a6a');
sinon.assert.calledOnce(getDataFromDbStub);
});
});
unit test result with coverage report:
a
B ctor
getDb
A getGuid
got guid 24f475b6-f9fa-495b-83f4-16f6b45b0a6a
✓ should pass (47ms)
b
B ctor
B getDataFromDb
✓ should pass
2 passing (65ms)
---------------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
---------------|---------|----------|---------|---------|-------------------
All files | 100 | 100 | 100 | 100 |
a.js | 100 | 100 | 100 | 100 |
b.js | 100 | 100 | 100 | 100 |
connection.js | 100 | 100 | 100 | 100 |
---------------|---------|----------|---------|---------|-------------------

Builder pattern ES6 nodejs

I've been having troubles when I try to call any builder "setter" methods
This is my code, User.js:
class User {
constructor(userBuilder) {
this.email = userBuilder.email;
this.name = userBuilder.name;
this.surname = userBuilder.surname;
this.photo = userBuilder.photo;
this.tokens = userBuilder.tokens;
this.authorized = userBuilder.authorized;
}
getEmail() {
return this.email;
}
getName() {
return this.name;
}
getSurname() {
return this.surname;
}
getPhoto() {
return this.photo;
}
getTokens() {
return this.tokens;
}
isAuthorized() {
return authorized;
}
static get UserBuilder() {
class UserBuilder {
constructor() {
this.email = null;
this.name = null;
this.surname = null;
this.photo = null;
this.tokens = null;
this.authorized = null;
}
email(email) {
this.email = email;
return this;
}
name(name) {
this.name = name;
return this;
}
surname(surname) {
this.surname = surname;
return this;
}
photo(photo) {
this.photo = photo;
return this;
}
tokens(tokens) {
this.tokens = tokens;
return this;
}
authorized(authorized) {
this.authorized = authorized;
return this;
}
build() {
return new User(this);
}
}
return UserBuilder;
}
}
module.exports = User
And my UserTest.spec.js:
process.env.NODE_ENV = 'test'
//Import User class
let User = require('../../../../main/com/auth/user/User');
// Import chai
let chai = require('chai');
// Tell chai that we'll be using the "should" style assertions.
chai.should();
describe('User', () => {
let user;
var email = "a#a";
var name = "a";
var surname = "a";
var photo = "p";
var authorized = true;
beforeEach(() => {
//Create new User object before each test
user = new User.UserBuilder()
.email(email)
.name(name)
.surname(surname)
.photo(photo)
.authorized(authorized)
.build();
});
it('returns the email', () => {
user.getEmail().should.equal(email)
});
it('returns the name', () => {
user.getName().should.equal(name)
});
it('returns the surname', () => {
user.getSurname().should.equal(surname)
});
it('returns the photo', () => {
user.getPhoto().should.equal(photo)
});
it('returns the authorized', () => {
user.getAuthorized().should.equal(authorized)
});
})
I get TypeError: user.email is not a function.
I've tried with UserBuilder outside User class:
In User.js
module.exports = {User: User, UserBuilder: UserBuilder}
In UserTest.spec.js
let {User} = require('../../../../main/com/auth/user/User');
let {UserBuilder} = require('../../../../main/com/auth/user/User');
user = new UserBuilder()
.email(email)
.name(name)
.surname(surname)
.photo(photo)
.authorized(authorized)
.build();
With the same result, what i'm doing wrong?? I can call build method, but I can't call any other methods.

Resources