__Rewire__ is not a function - javascript

Using Rewire for testing..
Rewire is failing to rewire, and I'm wondering why.
Here is an example of rewire failing:
A file has a few exported functions...
export function foo() {}
export function bar() {}
export function baz() {}
In a test file...
import * as pathFileHelpers from 'path/to/file';
pathFileHelpers.__Rewire__({
readFileSync: () => {
return 'test test test'
},
})
_get__(...).__Rewire__ is not a function
Why?

Related

How to write a webpack plugin to replace require function to its source code

Say we have a util.js contains functions a and b:
// util.js
export function a() {
...
}
export function b() {
...
}
And I require them in index.js:
// index.js
export default function main() {
const {a, b} = require('./util');
...
a(); // use them somewhere
b();
}
But I want to replace the require function to its source code like this before the bundling:
// replaced index.js
export default function main() {
const a = function () {
// ... source code from util.js
};
const b = function () {
// ... source code from util.js
};
...
a(); // use them somewhere
b();
}
I'm not that familiar with webpack plugins and hooks API.
Is this possible and if yes, how to do it?
Thanks!
One solution not that clever, do string replace directly by string-replace-loader.

Rewire private Typescript class methods

I'm trying to write unit tests for some private methods in my class using Typescript for my Node.js module.
I tried using rewire, but it's unable to access any methods (even public ones).
Here is my setup:
myclass.ts
class MyClass{
private somePrivateMethod() {
// do something
console.log(42);
}
public somePublicMethod() {
// do something
this.somePrivateMethod();
// do something
}
}
export default MyClass;
test.ts
import { expect } from 'chai';
import rewire from 'rewire';
describe('Test', function () {
describe('#somePrivateMethod()', function () {
const rewired = rewire('../src/myclass.ts');
//const rewired = rewire('../dist/myclass.js');
const method = rewired.__get__('somePrivateMethod');
});
});
I tried using rewire on the Typescript file and on the compiled JS file as well, but I get the same error:
ReferenceError: somePrivateMethod is not defined
I'm using Mocha with the following config:
'use strict';
module.exports = {
extension: ["ts"],
package: "./package.json",
reporter: "spec",
slow: 75,
timeout: 2000,
ui: "bdd",
"watch-files": ["test/**/*.ts"],
require: "ts-node/register",
};
Is there any solution for this problem?
I know is a pretty old question but if someone else find themself in the situation I've managed to find a solutions:
export class YourClass {
constructor( ) { }
private thisIsPrivate() {
//private stuff
}
otherPublicMethod() {
//public stuff
}
}
inside your test file you can import the class as usual to test public methods
import YourClass from '../src/classes/YourClass'
const testClass = new YourClass();
...
to test private methods import the class using rewire
import rewire from 'rewire'
const rewiredModule = rewire('../src/classes/YourClass')
const rewiredClass = rewiredModule.__get__('YourClass')
then inside your test
it('Test your private method', function () {
const myRewiredClassInstance = new rewiredClass()
myRewiredClassInstance.thisIsPrivate()
//do your expect here
}
The only downside is that the object returned is "any" and so no help from typescript.
you can even debug inside it if you have setup your debugger correctly
Enjoy everyone

Python like function mock in JavaScript

With Python it's so easy to mock a function that is used in the function under test.
# my_module.py
def function_a():
return 'a'
def function_b():
return function_a() + 'b'
# tests/test_my_module.py
from unittest import TestCase
from unittest.mock import patch
from my_module import function_b
class MyModuleTestCase(TestCase):
#patch('my_module.function_a')
def test_function_b(self, mock_function_a):
mock_function_a.return_value = 'c'
self.assertEqual(function_b(), 'cb')
Is something like this possible in JavaScript using, for example, jest?
# myModule.js
function myFunctionA() {
return 'a';
}
export function myFunctionB() {
return myFunctionA() + 'b';
}
# __test__/test.myModule.js
import { myFunctionB } from '../myModule';
describe('myModule tests', () => {
test('myFunctionB works', () => {
// Mock `myFunctionA` return value here somehow.
expect(myFunctionB()).toBe('cb')
});
});
I've read https://github.com/facebook/jest/issues/936 and still have no idea how to do it as there are so many (hacky) suggestions (some of them ~2 years old).
Jest can mock an entire module using jest.mock() or mock an individual module export using jest.spyOn() in combination with functions like mockImplementation().
This makes it easy to mock a function imported from a library:
// ---- lib.js ----
export function myFunctionA() {
return 'a';
}
// ---- myModule.js ----
import { myFunctionA } from './lib';
export function myFunctionB() {
return myFunctionA() + 'b'; // call lib.myFunctionA()
}
// ---- myModule.test.js ----
import { myFunctionB } from './myModule';
import * as lib from './lib';
describe('myModule tests', () => {
test('myFunctionB works', () => {
const mock = jest.spyOn(lib, 'myFunctionA'); // create a spy on lib.myFunctionA()
mock.mockImplementation(() => 'c'); // replace the implementation
expect(myFunctionB()).toBe('cb');
mock.mockRestore(); // remove the spy and mock implementation
});
});
In the code sample from the question myModule contains two functions and one calls the other directly.
Because a mock works on either an entire module or a module export, mocking the direct call to myFunctionA() from within myFunctionB() would be very difficult the way the code is written.
The easiest way I have found to work around situations like this is to import the module into itself and use the module when calling the function. That way it is the module export that is being called and it can be mocked in the test:
// ---- myModule.js ----
import * as myModule from './myModule';
export function myFunctionA() {
return 'a';
}
export function myFunctionB() {
return myModule.myFunctionA() + 'b'; // call myModule.myFunctionA()
}
// ---- myModule.test.js ----
import * as myModule from './myModule';
describe('myModule tests', () => {
test('myFunctionB works', () => {
const mock = jest.spyOn(myModule, 'myFunctionA'); // create a spy on myModule.myFunctionA()
mock.mockImplementation(() => 'c'); // replace the implementation
expect(myModule.myFunctionB()).toBe('cb');
mock.mockRestore(); // remove the spy and mock implementation
});
});

Jest test module while mocking function from same module

I am trying to verify that a function within a module calls another function within that module. When I try the following, Jest reports that bar was called 0 times. How can I test the function call successfully?
// module.js
function foo() {
bar()
}
function bar() {
...
}
export {foo, bar}
// __tests__/module-test.js
import * as module from "../module";
test("foo calls bar", () => {
module.bar = jest.fn();
module.foo();
expect(module.bar).toHaveBeenCalledTimes(1)
})

prototype function missing when calling third party node package in Angular 2+

I am trying to use a third party Node module in an angular 2+ project.
installed with npm install --save ModuleName
The function in question is in a file named Foo.js and looks like this:
var foo = function(param1, param2) {
...
this.init();
}
foo.protoype = {
constructor: foo,
init: function(){
...
},
...
}
module.exports = foo;
index.js for the node module looks like:
var ModuleName = require("./src/ModuleName");
ModuleName.foo = require("./src/Foo");
module.exports = ModuleName;
I am trying to use the module in a Directive:
import { Directive, OnInit } from '#angular/core';
import { ModuleName } from "ModuleName"
#Directive({
selector: '[customDirective]'
})
export class CustomDirective implements OnInit {
constructor() {
...
}
ngOnInit() {
let poorlyNamedVariable = ModuleName.foo(param1, param2);
}
}
When foo is called it produces ERROR TypeError: this.init is not a function
console.log(this) in foo shows an instance of ModuleName which, in turn, has an instance of foo, which has a prototype where init is defined.
I suspect the problem stems from some sort of scoping issue, but am still too new to both Angular and Node to untangle the mess.
Use import * as ModuleName from "ModuleName" for CommonJS modules.

Categories