How to stub exported function in ES6? - javascript

I have file foo.js:
export function bar (m) {
console.log(m);
}
And another file that uses foo.js, cap.js:
import { bar } from 'foo';
export default m => {
// Some logic that I need to test
bar(m);
}
I have test.js:
import cap from 'cap'
describe('cap', () => {
it('should bar', () => {
cap('some');
});
});
Somehow I need override implementation of bar(m) in test. Is there any way to do this?
P.S. I use babel, webpack and mocha.

Ouch.. I found solution, so I use sinon to stub and import * as foo from 'foo' to get object with all exported functions so I can stub them.
import sinon from 'sinon';
import cap from 'cap';
import * as foo from 'foo';
sinon.stub(foo, 'bar', m => {
console.log('confirm', m);
});
describe('cap', () => {
it('should bar', () => {
cap('some');
});
});

You can replace/rewrite/stub exports only from within the module itself. (Here's an explanation)
If you rewrite 'foo.js' like this:
var bar = function bar (m) {
console.log(m);
};
export {bar}
export function stub($stub) {
bar = $stub;
}
You can then override it in your test like this:
import cap from 'cap'
import {stub} from 'foo'
describe('cap', () => {
it('should bar', () => {
stub(() => console.log('stubbed'));
cap('some'); // will output 'stubbed' in the console instead of 'some'
});
});
I've created a Babel plugin that transforms all the exports automatically so that they can be stubbed: https://github.com/asapach/babel-plugin-rewire-exports

While #Mike solution would work in old versions of sinon, it has been removed since sinon 3.0.0.
Now instead of:
sinon.stub(obj, "meth", fn);
you should do:
stub(obj, 'meth').callsFake(fn)
Example of mocking google oauth api:
import google from 'googleapis';
const oauth2Stub = sinon.stub();
sinon.stub(google, 'oauth2').callsFake(oauth2Stub);
oauth2Stub.withArgs('v2').returns({
tokeninfo: (accessToken, params, callback) => {
callback(null, { email: 'poo#bar.com' }); // callback with expected result
}
});

You can use babel-plugin-rewire (npm install --save-dev babel-plugin-rewire)
And then in test.js use the __Rewire__ function on the imported module to replace the function in that module:
// test.js
import sinon from 'sinon'
import cap from 'cap'
describe('cap', () => {
it('should bar', () => {
const barStub = sinon.stub().returns(42);
cap.__Rewire__('bar', barStub); // <-- Magic happens here
cap('some');
expect(barStub.calledOnce).to.be.true;
});
});
Be sure to add rewire to your babel plugins in .babelrc:
// .babelrc
{
"presets": [
"es2015"
],
"plugins": [],
"env": {
"test": {
"plugins": [
"rewire"
]
}
}
}
Lastly, as you can see the babel-plugin-rewire plugin is only enabled in the test environment, so you should call you test runner with the BABEL_ENV environment variable set to test (which you're probably doing already):
env BABEL_ENV=test mocha --compilers js:babel-core/register test-example.js
Note: I couldn't get babel-plugin-rewire-exports to work.

This was definitely a gotcha for me too...
I created a little util to workaround this limitation of sinon. (Available in js too).
// mockable.ts 👇
import sinon from 'sinon'
export function mockable<T extends unknown[], Ret>(fn: (...fnArgs: T) => Ret) {
let mock: sinon.SinonStub<T, Ret> | undefined
const wrapper = (...args: T) => {
if (mock) return mock(...args)
return fn(...args)
}
const restore = () => {
mock = undefined
}
wrapper.mock = (customMock?: sinon.SinonStub<T, Ret>) => {
mock = customMock || sinon.stub()
return Object.assign(mock, { restore })
}
wrapper.restore = restore
return wrapper
}
If you paste the above snippet into your project you can use it like so
foo.js
import { mockable } from './mockable'
// we now need to wrap the function we wish to mock
export const foo = mockable((x) => {
console.log(x)
})
main.js
import { foo } from './foo'
export const main = () => {
foo('asdf') // use as normal
}
test.js
import { foo } from './foo'
import { main } from './main'
// mock the function - optionally pass in your own mock
const mock = foo.mock()
// test the function
main()
console.assert(mock.calledOnceWith('asdf'), 'not called')
// restore the function
stub.restore()
The benefit of this approach is that you don't have to remember to always import the function in a certain way. import { foo } from './foo' works just as well as import * as foo from './foo'. Automatic imports will likely just work in your IDE.

Related

How to spyOn an exported standalone function using javascript jest?

It is a very simple scenario but I've struggled to find an answer for it.
helpers.ts:
export function foo() {
bar();
}
export function bar() {
// do something
}
helpers.spec.ts:
import { foo, bar } from "./helpers";
describe("tests", () => {
it("example test", () => {
const barSpy = // how can i set this up?
foo();
expect(barSpy).toHaveBeenCalled();
});
});
I can't do const spy = jest.spyOn(baz, 'bar'); because I don't have a module/class to put in place of "baz". It is just an exported function.
Edit:
Jest mock inner function has been suggested as a duplicate but unfortunately it doesn't help with my scenario.
Solutions in that question:
Move to separate module: I cannot do this for my scenario. If I am testing every function in my application, this would result in me creating 10s of new files which is not ideal. (To clarify, I think this solution would work but I cannot use it for my scenario. I am already mocking a separate file function successfully in this test file.)
Import the module into itself:
helpers.spec.ts:
import * as helpers from "./helpers";
describe("tests", () => {
it("example test", () => {
const barSpy = jest.spyOn(helpers, 'bar');
foo();
expect(barSpy).toHaveBeenCalled();
});
});
results in:
expect(jest.fn()).toHaveBeenCalled()
Expected number of calls: >= 1
Received number of calls: 0
This is the closed solution:
export function bar() {
// do something
}
export function foo() {
exports.bar(); // <-- have to change to exports.bar() instead of bar()
// or this.bar(); would also work.
}
import * as utils from './utils';
describe('tests', () => {
it('example test', () => {
const barSpy = jest.spyOn(utils, 'bar');
utils.foo();
expect(barSpy).toHaveBeenCalled();
});
});
Or take a look this duplicated question

How to use an async function as the second parameter to jest.mock?

I need to use jest.mock together with async, await and import() so that I can use a function from another file inside the mocked module. Otherwise I must copy and paste a few hundreds of slocs or over 1000 slocs, or probably it is not even possible.
An example
This does work well:
jest.mock('./myLin.jsx', () => {
return {
abc: 967,
}
});
Everywhere I use abc later it has 967 as its value, which is different than the original one.
This does not work:
jest.mock('./myLin.jsx', async () => {
return {
abc: 967,
}
});
abc seems to not be available.
Actual issue
I need async to be able to do this:
jest.mock('~/config', async () => {
const { blockTagDeserializer } = await import(
'../editor/deserialize' // or 'volto-slate/editor/deserialize'
);
// … here return an object which contains a call to
// blockTagDeserializer declared above; if I can't do this
// I cannot use blockTagDeserializer since it is outside of
// the scope of this function
}
Actual results
I get errors like:
TypeError: Cannot destructure property 'slate' of '((cov_1viq84mfum.s[13]++) , _config.settings)' as it is undefined.
where _config, I think, is the ~/config module object and slate is a property that should be available on _config.settings.
Expected results
No error, blockTagDeserializer works in the mocked module and the unit test is passed.
The unit test code
The code below is a newer not-working code based on this file on GitHub.
import React from 'react';
import renderer from 'react-test-renderer';
import WysiwygWidget from './WysiwygWidget';
import configureStore from 'redux-mock-store';
import { Provider } from 'react-intl-redux';
const mockStore = configureStore();
global.__SERVER__ = true; // eslint-disable-line no-underscore-dangle
global.__CLIENT__ = false; // eslint-disable-line no-underscore-dangle
jest.mock('~/config', async () => {
const { blockTagDeserializer } = await import(
'../editor/deserialize' // or 'volto-slate/editor/deserialize'
);
const createEmptyParagraph = () => {
return {
type: 'p',
children: [{ text: '' }],
};
};
return {
settings: {
supportedLanguages: [],
slate: {
elements: {
default: ({ attributes, children }) => (
<p {...attributes}>{children}</p>
),
strong: ({ children }) => {
return <strong>{children}</strong>;
},
},
leafs: {},
defaultBlockType: 'p',
textblockExtensions: [],
extensions: [
(editor) => {
editor.htmlTagsToSlate = {
STRONG: blockTagDeserializer('strong'),
};
return editor;
},
],
defaultValue: () => {
return [createEmptyParagraph()];
},
},
},
};
});
window.getSelection = () => ({});
test('renders a WysiwygWidget component', () => {
const store = mockStore({
intl: {
locale: 'en',
messages: {},
},
});
const component = renderer.create(
<Provider store={store}>
<WysiwygWidget
id="qwertyu"
title="My Widget"
description="My little description."
required={true}
value={{ data: 'abc <strong>def</strong>' }}
onChange={(id, data) => {
// console.log('changed', data.data);
// setHtml(data.data);
}}
/>
</Provider>,
);
const json = component.toJSON();
expect(json).toMatchSnapshot();
});
What I've tried
The code snippets above show partially what I have tried.
I searched the web for 'jest mock async await import' and did not found something relevant.
The question
If jest.mock is not made to work with async, what else can I do to make my unit test work?
Update 1
In the last snippet of code above, the line
STRONG: blockTagDeserializer('strong'),
uses blockTagDeserializer defined here which uses deserializeChildren, createEmptyParagraph (which is imported from another module), normalizeBlockNodes (which is imported from another module) and jsx (which is imported from another module) functions, which use deserialize which uses isWhitespace which is imported from another module and typeDeserialize which uses jsx and deserializeChildren.
Without using await import(...) syntax how can I fully mock the module so that my unit test works?
If you want to dig into our code, please note that the volto-slate/ prefix in the import statements is for the src/ folder in the repo.
Thank you.
I'd advise not doing any "heavy" stuff (whatever that means) in a callback of jest.mock, – it is designed only for mocking values.
Given your specific example, I'd just put whatever the output of blockTagDeserializer('strong') right inside the config:
jest.mock('~/config', () => {
// ...
extensions: [
(editor) => {
editor.htmlTagsToSlate = {
STRONG: ({ children }) => <strong>{children}</strong>, // or whatever this function actually returns for 'strong'
};
return editor;
},
],
// ...
});
This doesn't require anything asynchronous to be done.
If you need this setup to be present in a lot of files, extracting it in a setup file seems to be the next best thing.
I found a solution. I have a ref callback that sets the htmlTagsToSlate property of the editor in the actual code of the module, conditioned by global.__JEST__ which is defined as true in Jest command line usage:
import { htmlTagsToSlate } from 'volto-slate/editor/config';
[...]
testingEditorRef={(val) => {
ref.current = val;
if (val && global.__JEST__) {
val.htmlTagsToSlate = { ...htmlTagsToSlate };
}
}}
Now the jest.mock call for ~/config is simple, there is no need to do an import in it.
I also use this function:
const handleEditorRef = (editor, ref) => {
if (typeof ref === 'function') {
ref(editor);
} else if (typeof ref === 'object') {
ref.current = editor;
}
return editor;
};

Jest: How to mock custom module that is exported from an index.js file?

This is the structure of my project (create-react-app):
Contents of /src/api/searchAPI.js:
import client from './client';
async function searchMulti(query, options = {}) {
options.query = query;
return await client.get('/search/multi', options);
}
export default {
searchMulti
};
Contents of /src/api/index.js:
import movieAPI from './movieAPI';
import personAPI from './personAPI';
import searchAPI from './searchAPI';
import configurationAPI from './configurationAPI';
export { movieAPI, personAPI, searchAPI, configurationAPI };
QuickSearch component imports searchAPI ands uses it to fetch some data over the web.
Now, I need to test (with react-testing-library) the QuickSearch component.
So, I would like to mock the api module (exported in /src/api/index.js) in order to use a mock function instead of searchAPI.searchMulti( ).
If I put below code in /src/componentns/__tests__/QuickSearch.js, it works just fine:
...
import { searchAPI } from '../../
...
...
jest.mock('../../api', () => {
return {
searchAPI: {
searchMulti: jest.fn().mockResolvedValue({ results: [] })
}
};
});
...
it('some test', () => {
searchAPI.searchMulti.mockResolvedValueOnce({ results: [] });
const { queryByTitle, getByPlaceholderText } = renderWithRouter(
<QuickSearch />
);
const input = getByPlaceholderText(/Search for a movie or person/i);
expect(searchAPI.searchMulti).not.toHaveBeenCalled();
act(() => {
fireEvent.change(input, { target: { value: 'Aladdin' } });
});
expect(searchAPI.searchMulti).toHaveBeenCalledTimes(1);
});
My problem is that I don't want to mock api in every test file that needs it. Instead, I would like to put api in a __mocks__ folder so that other tests can use it you, too.
How can I do that?

Mock dependency in Jest with TypeScript

When testing a module that has a dependency in a different file and assigning that module to be a jest.mock, TypeScript gives an error that the method mockReturnThisOnce (or any other jest.mock method) does not exist on the dependency, this is because it is previously typed.
What is the proper way to get TypeScript to inherit the types from jest.mock?
Here is a quick example.
Dependency
const myDep = (name: string) => name;
export default myDep;
test.ts
import * as dep from '../depenendency';
jest.mock('../dependency');
it('should do what I need', () => {
//this throws ts error
// Property mockReturnValueOnce does not exist on type (name: string)....
dep.default.mockReturnValueOnce('return')
}
I feel like this is a very common use case and not sure how to properly type this.
You can use type casting and your test.ts should look like this:
import * as dep from '../dependency';
jest.mock('../dependency');
const mockedDependency = <jest.Mock<typeof dep.default>>dep.default;
it('should do what I need', () => {
//this throws ts error
// Property mockReturnValueOnce does not exist on type (name: string)....
mockedDependency.mockReturnValueOnce('return');
});
TS transpiler is not aware that jest.mock('../dependency'); changes type of dep thus you have to use type casting. As imported dep is not a type definition you have to get its type with typeof dep.default.
Here are some other useful patterns I've found during my work with Jest and TS
When imported element is a class then you don't have to use typeof for example:
import { SomeClass } from './SomeClass';
jest.mock('./SomeClass');
const mockedClass = <jest.Mock<SomeClass>>SomeClass;
This solution is also useful when you have to mock some node native modules:
import { existsSync } from 'fs';
jest.mock('fs');
const mockedExistsSync = <jest.Mock<typeof existsSync>>existsSync;
In case you don't want to use jest automatic mock and prefer create manual one
import TestedClass from './TestedClass';
import TestedClassDependency from './TestedClassDependency';
const testedClassDependencyMock = jest.fn<TestedClassDependency>(() => ({
// implementation
}));
it('Should throw an error when calling playSomethingCool', () => {
const testedClass = new TestedClass(testedClassDependencyMock());
});
testedClassDependencyMock() creates mocked object instance
TestedClassDependency can be either class or type or interface
Use the mocked helper
like explained here
// foo.spec.ts
import { foo } from './foo'
jest.mock('./foo')
// here the whole foo var is mocked deeply
const mockedFoo = jest.mocked(foo, true)
test('deep', () => {
// there will be no TS error here, and you'll have completion in modern IDEs
mockedFoo.a.b.c.hello('me')
// same here
expect(mockedFoo.a.b.c.hello.mock.calls).toHaveLength(1)
})
test('direct', () => {
foo.name()
// here only foo.name is mocked (or its methods if it's an object)
expect(jest.mocked(foo.name).mock.calls).toHaveLength(1)
})
There are two solutions tested for TypeScript version 3.x and 4.x, both are casting desired function
1) Use jest.MockedFunction
import * as dep from './dependency';
jest.mock('./dependency');
const mockMyFunction = dep.myFunction as jest.MockedFunction<typeof dep.myFunction>;
2) Use jest.Mock
import * as dep from './dependency';
jest.mock('./dependency');
const mockMyFunction = dep.default as jest.Mock;
There is no difference between these two solutions. The second one is shorter and I would therefore suggest using that one.
Both casting solutions allows to call any jest mock function on mockMyFunction like mockReturnValue or mockResolvedValue
https://jestjs.io/docs/en/mock-function-api.html
mockMyFunction.mockReturnValue('value');
mockMyFunction can be used normally for expect
expect(mockMyFunction).toHaveBeenCalledTimes(1);
I use the pattern from #types/jest/index.d.ts just above the type def for Mocked (line 515):
import { Api } from "../api";
jest.mock("../api");
const myApi: jest.Mocked<Api> = new Api() as any;
myApi.myApiMethod.mockImplementation(() => "test");
Cast as jest.Mock
Simply casting the function to jest.Mock should do the trick:
(dep.default as jest.Mock).mockReturnValueOnce('return')
Use as jest.Mock and nothing else
The most concise way of mocking a module exported as default in ts-jest that I can think of really boils down to casting the module as jest.Mock.
Code:
import myDep from '../dependency' // No `* as` here
jest.mock('../dependency')
it('does what I need', () => {
// Only diff with pure JavaScript is the presence of `as jest.Mock`
(myDep as jest.Mock).mockReturnValueOnce('return')
// Call function that calls the mocked module here
// Notice there's no reference to `.default` below
expect(myDep).toHaveBeenCalled()
})
Benefits:
does not require referring to the default property anywhere in the test code - you reference the actual exported function name instead,
you can use the same technique for mocking named exports,
no * as in the import statement,
no complex casting using the typeof keyword,
no extra dependencies like mocked.
The latest jest allows you to do this very easily with jest.mocked
import * as dep from '../dependency';
jest.mock('../dependency');
const mockedDependency = jest.mocked(dep);
it('should do what I need', () => {
mockedDependency.mockReturnValueOnce('return');
});
Here's what I did with jest#24.8.0 and ts-jest#24.0.2:
source:
class OAuth {
static isLogIn() {
// return true/false;
}
static getOAuthService() {
// ...
}
}
test:
import { OAuth } from '../src/to/the/OAuth'
jest.mock('../src/utils/OAuth', () => ({
OAuth: class {
public static getOAuthService() {
return {
getAuthorizationUrl() {
return '';
}
};
}
}
}));
describe('createMeeting', () => {
test('should call conferenceLoginBuild when not login', () => {
OAuth.isLogIn = jest.fn().mockImplementationOnce(() => {
return false;
});
// Other tests
});
});
This is how to mock a non-default class and it's static methods:
jest.mock('../src/to/the/OAuth', () => ({
OAuth: class {
public static getOAuthService() {
return {
getAuthorizationUrl() {
return '';
}
};
}
}
}));
Here should be some type conversion from the type of your class to jest.MockedClass or something like that. But it always ends up with errors. So I just used it directly, and it worked.
test('Some test', () => {
OAuth.isLogIn = jest.fn().mockImplementationOnce(() => {
return false;
});
});
But, if it's a function, you can mock it and do the type conversation.
jest.mock('../src/to/the/Conference', () => ({
conferenceSuccessDataBuild: jest.fn(),
conferenceLoginBuild: jest.fn()
}));
const mockedConferenceLoginBuild = conferenceLoginBuild as
jest.MockedFunction<
typeof conferenceLoginBuild
>;
const mockedConferenceSuccessDataBuild = conferenceSuccessDataBuild as
jest.MockedFunction<
typeof conferenceSuccessDataBuild
>;
As of Jest 24.9.0 here is how you can mock and correctly type both your Class/Object/function and Jest properties.
jest.MockedFunction
jest.MockedClass
What we would like for a typed mock is that the mocked object type contains the union of the mocked object type and the type of Jest mocks.
import foo from 'foo';
jest.mock('foo');
const mockedFoo = foo as jest.MockedFunction<typeof foo>;
// or: const mockedFooClass = foo as jest.MockedClass<typeof FooClass>;
mockedFoo.mockResolvedValue('mockResult');
// Or:
(mockedFoo.getSomething as jest.MockedFunction<typeof mockedFoo.getSomething>).mockResolvedValue('mockResult');
As you can see, you can either manually cast what you need or you'll need something to traverse all foo's properties/methods to type/cast everything.
To do that (deep mock types) you can use jest.mocked() introduced in Jest 27.4.0
import foo from 'foo';
jest.mock('foo');
const mockedFoo = jest.mocked(foo, true);
mockedFoo.mockImplementation() // correctly typed
mockedFoo.getSomething.mockImplementation() // also correctly typed
I have found this in #types/jest:
/**
* Wrap a function with mock definitions
*
* #example
*
* import { myFunction } from "./library";
* jest.mock("./library");
*
* const mockMyFunction = myFunction as jest.MockedFunction<typeof myFunction>;
* expect(mockMyFunction.mock.calls[0][0]).toBe(42);
*/
Note: When you do const mockMyFunction = myFunction and then something like mockFunction.mockReturnValue('foo'), you're a changing myFunction as well.
Source: https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/jest/index.d.ts#L1089
The top rated solution by Artur Górski does not work with the last TS and Jest.
Use MockedClass
import SoundPlayer from '../sound-player';
jest.mock('../sound-player'); // SoundPlayer is now a mock constructor
const SoundPlayerMock = SoundPlayer as jest.MockedClass<typeof SoundPlayer>;
A recent library solves this problem with a babel plugin: https://github.com/userlike/joke
Example:
import { mock, mockSome } from 'userlike/joke';
const dep = mock(import('./dependency'));
// You can partially mock a module too, completely typesafe!
// thisIsAMock has mock related methods
// thisIsReal does not have mock related methods
const { thisIsAMock, thisIsReal } = mockSome(import('./dependency2'), () => ({
thisIsAMock: jest.fn()
}));
it('should do what I need', () => {
dep.mockReturnValueOnce('return');
}
Be aware that dep and mockReturnValueOnce are fully type safe. On top, tsserver is aware that depencency was imported and was assigned to dep so all automatic refactorings that tsserver supports will work too.
Note: I maintain the library.
This is ugly, and in fact getting away from this ugliness is why I even looked at this question, but to get strong typing from a module mock, you can do something like this:
const myDep = (require('./dependency') as import('./__mocks__/dependency')).default;
jest.mock('./dependency');
Make sure you require './dependency' rather than the mock directly, or you will get two different instantiations.
For me this was enough:
let itemQ: queueItemType
jest.mock('../dependency/queue', () => {
return {
add: async (item: queueItemType, ..._args: any) => {
// then we can use the item that would be pushed to the queue in our tests
itemQ = item
return new Promise(resolve => {
resolve('Mocked')
})
},
}
})
Then, whenever the add method is called it will execute this code above instead of pushing it to the queue, in this case.
With TypeScript 2.8 we can do like this with ReturnType:
import * as dep from "./depenendency"
jest.mock("./dependency")
const mockedDependency = <jest.Mock<ReturnType<typeof dep.default>>>dep.default
it("should do what I need", () => {
mockedDependency.mockReturnValueOnce("return")
})

Using proxyquire in a browserify factor bundle

Stuck with this one.
I am using laravel elxir with tsify to generate my js. I run the typescript through factor-bundle to split common js modules into a seperate files. I don't think though that will be a problem in this case because everything is in a spec.js
spec.ts
/// <reference path="../../../typings/index.d.ts" />
import "jasmine-jquery";
// #start widgets
import "./widgets/common/widget-factory/test";
factory-widget/index.ts
export class WidgetFactory {
.... this contains a require call to browser.service which i need to mock
}
factory-widget/test.ts
...
import {WidgetFactory} from "./index";
const proxyRequire = require("proxyquire");
it("should output the factory items", ()=> {
proxyRequire('./widgets/browser.service/index',{
"#global": true,
});
}
browser-service.ts
...
export class BrowserService implements IBrowserService{
//details
}
Getting an error Uncaught TypeError: require.resolve is not a function on line 262.
Here is the code ( yeah it's over 20,000 lines ) how else are you supposed to debug this stuff . ¯_(ツ)_/¯
I've looked at Stubbing with proxyquire. I am not holding my breath getting an answer on this one.
Edit: 06-09-2016
Proxquire is needed to overide the require call in the boot method of the WidgetFactory class
In factory-widget/index.ts:
boot(output = true):any {
let required = {};
if (this._sorted.length) {
this._sorted.forEach((key)=> {
if (output) {
console.log(`${this._path}${key}/index`);
// this is where is need to overide the call to require.
required[key] = require(`${this._path}${key}/index`);
}
});
this._sorted.forEach((key)=> {
let dependencies = {},
module = this._factory[key];
if (module.hasOwnProperty(this.dependencyKey)) {
module[this.dependencyKey].map((key)=> {
dependencies[_.camelCase(key)] = this.isService(module) ? new required[key] : key;
});
}
if (this.isTag(module)) {
if (output) {
document.addEventListener("DOMContentLoaded", ()=> {
riot.mount(key, dependencies);
});
}
//console.log(key,dependencies);
}
else {
}
})
}
}
I've added a proxyquireify example to the tsify GitHub repo. It's based on the simple example in the proxyquireify README.md.
The significant parts are the re-definition of require to call proxyquire in foo-spec.ts:
const proxyquire = require('proxyquireify')(require);
require = function (name) {
const stubs = {
'./bar': {
kinder: function () { return 'schokolade'; },
wunder: function () { return 'wirklich wunderbar'; }
}
};
return proxyquire(name, stubs);
} as NodeRequire;
and the configuration of the proxyquire plugin in build.js:
browserify()
.plugin(tsify)
.plugin(proxyquire.plugin)
.require(require.resolve('./src/foo-spec.ts'), { entry: true })
.bundle()
.pipe(process.stdout);
If you build the bundle.js and run it under Node.js, you should see that the message written to the console includes strings returned by the functions in the stubbed ./bar module.

Categories

Resources