How to stub constant functions when using ES Modules with sinon.js?

戏子无情 提交于 2019-12-24 01:39:32

问题


With ES Modules, we define some exported functions as const and it is often a standard practice. However, during unit testing, these const functions can't be stubbed out which seems problematic from a unit testing perspective. For example,

import * as fs from 'fs';

import { bindNodeCallback } from 'rxjs';
import { map } from 'rxjs/operators';

// readFile :: string, string => Observable<string>
export const readFile$ = bindNodeCallback(fs.readFile);

// readJson :: string => Observable<any>
export function readJson(fileName) {
    return readFile$(fileName, 'utf-8')
        .pipe(map((rawFile) => JSON.parse(rawFile)));
}

Now to unit test readJson, I would typically want to stub readFile$ function. Unfortunately, following Sinon code doesn't work:

// Setup data - stubs / mocks
const stub = sinon.stub(myFs, 'readFile$').returns(json$);

Since Sinon is simply changing reference myFs.readFile$, original const still points to the original function which is in turn called by readJson function.

Any suggestion - how can I really stub/mock constant function within the same module?


回答1:


const is constant one can't change it using "normal" code. Unfortunately sinon is not magic. You need to instrument your code to allow changing constant value.

Assuming you are using babel to transpile you could use babel-plugin-rewire.

After adding it to your babel config you would be able to do the following injection in your test code

import { default as readJson, __RewireAPI__ as rewire } from './path/to/readJson.js'

const stub = sinon.stub(myFs, 'readFile$').returns(json$)
rewire.__set__('readFile$', stub)

// readJson() would now call provided stub


来源:https://stackoverflow.com/questions/50460750/how-to-stub-constant-functions-when-using-es-modules-with-sinon-js

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!