Why is the constructor invoked despite calling createStubInstance? - node.js

I want to prevent the constructor of a class being called during a test so I used createStubInstance(MyClass) as per the docs, but the constructor still gets invoked. Why?
If you want to create a stub object of MyConstructor, but don’t want
the constructor to be invoked, use this utility function.
var stub = sinon.createStubInstance(MyConstructor)
Test
const sinon = require('sinon')
const Fizz = require('../Fizz')
const Buzz = require('../Buzz')
describe('Fizz', () => {
it('should mock the constructor', () => {
sinon.createStubInstance(Fizz)
const doStuffFakeFizz = sinon.stub(Fizz.prototype, 'doStuff').returns({ src: 'mock' })
const buzz = new Buzz()
buzz.doStuff()
expect(doStuffFakeFizz.called).toBeTruthy()
})
})
Buzz
const Fizz = require('./Fizz')
class Buzz {
doStuff() {
const fizz = new Fizz()
return fizz.doStuff()
}
}
module.exports = Buzz
Fizz
class Fizz {
constructor() {
console.log('CALLED')
this.thing = { src: 'real' }
}
doStuff() {
return this.thing
}
}
module.exports = Fizz

sinon.createStubInstance can't replace references like that. All it does is return a plain object with a stub in place for each property in the constructor's prototype. You'll usually make this object the return value of some stub, or provide it as an argument somewhere, in order to get it into place.
In order to actually stub the Fizz constructor, your code under test needs to invoke it by means of a reference that can be replaced. See my answer here:
Can ES6 constructors be stubbed more easily with Sinon?

Related

How to mock with JestJS injected dependency in class ES6?

I'm trying to get some dependance inversion going in a small NodeJS project. I want to have mocked instances of personal classes that I can inject in other classes.
This is for the lates node and jest version, I have read Jest documentation and nothing seem to be what I'm looking for.
class A {
getStr(): string {
return "bob";
}
}
class B {
private a: A;
constructor(a: A){
this.a = a;
}
getA(): string {
return a.getStr();
}
}
const b = new B(mocked instance of A)
I expect to be able to interact with the injected mock and see if it's been called in unit testing.
Assuming you would like to spy on the functions of A, you could do it as follows (if you would like to keep using classes notation):
class MockA {
constructor() {
this.getStr = jest.fn()
}
}
const mockedA = new MockA()
const b = new B(mockedA)
Then to test that it was called, you could do it as follows:
b.getA();
expect(a.getStr.mock.calls.length).toBe(1)
To create the mock without the class, you could do so as follows:
const mockedGetStr = jest.fn()
const b = new B({ getStr: mockedGetStr })
b.getA();
expect(a.getStr.mock.calls.length).toBe(1)

How to call remove listener on EventEmitter in nodejs?

I have below code to add listeners on EventEmitter,
class MyClass {
init() {
this.listener = new EventEmitter();
this.listener.on('eventName', this.onChange.bind(this));
}
onChange() {
...
}
}
How can I remove the listener from EventEmitter? I can see two different ways:
this.listener.removeListener('eventName', this.onChange)
this.listener.removeListener('eventName', this.onChange.bind(this))
I wonder which one I should use. Whether I need the bind when I remove it?
You can use bind() or you can use an Arrow Function in Node. Arrow Functions will inherit their execution context from the invoking context, which is similar to how bind() works and provides the same functionality.
this.listener.removeListener('eventName', this.onChange)
The above way of removing a listener won't work if it is being called in a removeListener(eventName) style function like the following:
const obj = new MyObject()
obj.init()
// This would blow up with a
// ReferenceError saying you cant call removeListener() on undefined
obj.listener.removeListener('event')
Not sure the use of the init() function when you can use a constructor with the class syntax.
constructor() {
this.listener = new EventEmitter()
this.boundEventNameHandler = () => this.onChange()
this.listener.on('eventName', this.boundEventNameHandler)
}
You can utilize the bound function for removing a listener within the context of a class using this.
let boundEventNameHandler = this.boundEventNameHandler
this.listener.removeListener('eventName', this.boundEventNameHandler)`
An example of this implemented looks like the following
const EventEmitter = require('events')
class MyObject {
constructor () {
this.listener = new EventEmitter()
this.boundEventNameHandler = () => this.onChange()
this.listener.on('eventName', this.boundEventNameHandler)
}
// I would reconsider making this a property of the MyObject class
// instead, make onChange() a local function outside the MyObject
// class definition because onChange in this example is only used by the
// event listener for 'eventName'
onChange () {
console.log('event fired change')
}
removeListeners () {
let boundEventNameHandler = this.boundEventNameHandler
this.listener.removeListener('eventName', boundEventNameHandler)
}
}
For TypeScript / ESNext you can use this:
class MyClass {
constructor() {
this.emitter = new EventEmitter();
this.emitter.on("event1", this.listener1);
this.emitter.on("event2", this.listener2);
this.emitter.removeListener("event1", this.listener1);
this.emitter.removeListener("event2", this.listener2);
this.emitter.emit("event1"); // no output
this.emitter.emit("event2"); // no output
}
public listener1 = (e) => {
console.dir(`listener1`);
};
public listener2 = (e) => {
console.dir(`listener2`);
};
}
Basically you define properties and instantly assign bound functions to them.
This way you use the same function reference in .on and .removeListener.

Node.js performance

Imagine, we got 2 simple classes (omitted export):
class SomeService {
async func () {
// some async function logic
return value;
}
}
class SomeController {
constructor (service) {
this.service = service;
}
async func () {
const value = await this.service.func();
// some controller-specific logic here
return value;
}
}
Also, we got simple function, that use this two classes in two ways.
Case one:
// require clasess
const somefunc = async () => {
const controller = new SomeController(new SomeService());
const value = await controller.func();
return value;
}
module.exports = somefunc;
Case two:
// require clasess
const controller = new SomeController(new SomeService());
const somefunc = async () => {
const value = await controller.func();
return value;
}
module.exports = somefunc;
As far as i understand how node's require works in the first case controller will be created each time when the somefunc is called. In the second case controller is created only one time, when the file will be evaluated. What case is better and more importantly what should i read or lookup to understand why?
I imagine the answer depends on your use-case. You have to ask yourself if you need to recreate SomeController every time that the function is called or not. Another thing to also consider is whether SomeController relies on something async when being initialized. For instance, if the controller needs access to a database connection in its constructor, then you'd have to wait for the database connection to be established. In situations like that, you may have no choice but to initialize SomeController inside the function. As I said, there's no objective better in cases like this. It's all dependent on your use-case.

With TypeScript: unable to refer to 'this' (class) from inside a function

I'm learning TypeScript and have the following class:
class DetailDriver {
public get driver() {
return super.getEntity();
}
public activate(): breeze.Promise {
var id = this.driver.id(); // this refers to (class) DetailDriver
return promise
.then(getCertificate)
.fail(somethingWrong);
function getCertificate() {
var id = this.driver.id(); // this refers to any
return ...
}
}
}
As you can see on the above code, the first call to this refers to my class DetailDriver. That's good. The second call to this (inside getCertificate) refers to any. That's not what I need. I need to refer to my class DetailDriver.
How to proceed?
Thanks.
Well,
According to section 4.9.2 of the TypeScript Language Specification you should use fat arrow syntax to preserve the scoping for this.
return promise
.then(() => return.this.id;)
.fail(somethingWrong);
Then the this keyword is properly determined to be a Driver.
For reference, you could also just do:
class SomeClass {
public someMethod() {
// Do something
}
public anotherMethod() {
var that = this; // Reference the class instance
function someFunction () {
that.someMethod();
}
}
}
You could refactor to something like this:
class DetailDriver {
public get driver() {
return super.getEntity();
}
public activate(): breeze.Promise {
var id = this.driver.id(); // this refers to (class) DetailDriver
return promise
.then(this.getCertificate.bind(this)) // <- important part
.fail(somethingWrong);
}
// new method function here
private getCertificate() {
var id = this.driver.id(); // this refers to any
return ...
}
}
Using the function keyword anywhere in your class will make any reference to this keyword refer to that function rather than the outer class. Generally, you want to avoid defining functions inside of classes, unless you use the "fat arrow" syntax. That would look like this:
class DetailDriver {
public get driver() {
return super.getEntity();
}
public activate(): breeze.Promise {
var id = this.driver.id(); // this refers to (class) DetailDriver
return promise
.then(() => { // <- important part
var id = this.driver.id(); // this refers to any
return ...
})
.fail(somethingWrong);
}
}

PreloadJS + Typescript

I have been stuck for 4 days so it is going on SO!
Please reference the PreloadJS Definitions:
https://github.com/borisyankov/DefinitelyTyped/blob/master/preloadjs/preloadjs.d.ts
From line 26.
My question is, how do you addEventListener in typescript while also binding it to the class scope?
imagine (semi psudo):
class Test
{
private _loader:createJS.AssetLoader;
constructor()
{
this._loader = new createJS.AssetLoader();
this._loader.addEventListener(???????????);
this._loader.load();
}
onLoadComplete(???): ???
{
}
}
Using TypeScript 0.9.1.0:
class Test
{
private _loader: createJS.AssetLoader;
constructor()
{
this._loader = new createJS.AssetLoader();
this._loader.addEventListenerthis.onLoadComplete);
this._loader.load();
}
onLoadComplete = () =>
{
console.log(this.whatever);
};
}
The important part here is using the member initialization syntax (member = value) for onLoadComplete and using a fat arrow lambda expression (() => { ... }) for the function. This will correctly capture the this context in the callback.

Resources