我有一个名为 helper.js 的文件,其中包含两个功能
export const funcA = (key) => {
return funcB(key)
};
export const funcB = (key,prop) => {
return someObj;
};
我有我的 helper.spec.js 来测试helper.js文件功能。
import {funcA,funcB} from 'helper';
describe('helper', () => {
test('testFuncB', () => {
}
test('testFuncA', () => {
}
}
对于funcB的测试非常简单,我将其命名为 someObj
问题是要测试funcA,为了测试它,我想模拟funcB的响应。
我希望 testFuncB 呼叫实际的 funcB 和 testFuncA 嘲笑的 funcB
我如何在两个测试中实现对funcB的模拟和原创?
这不是重复项。这是另一种情况:它们仅模拟内部调用的函数,如果我删除了testFuncB,那将是相同的,但是我也必须对testFuncB进行测试。
答案 0 :(得分:4)
如果ES6模块直接导出两个函数(不在类,对象等内部,而是直接导出问题中的函数),而一个直接调用另一个,则该调用不能被模拟。
在这种情况下,funcB
在funcA
内不能被模仿。
模拟代替了funcB
的模块导出,但是funcA
并未调用funcB
的模块导出,它只是直接调用funcB
。
在funcB
中模拟funcA
要求funcA
调用funcB
的模块导出。
这可以通过以下两种方式之一完成:
将funcB
移至其自己的模块
funcB.js
export const funcB = () => {
return 'original';
};
helper.js
import { funcB } from './funcB';
export const funcA = () => {
return funcB();
};
helper.spec.js
import * as funcBModule from './funcB';
import { funcA } from './helper';
describe('helper', () => {
test('test funcB', () => {
expect(funcBModule.funcB()).toBe('original'); // Success!
});
test('test funcA', () => {
const spy = jest.spyOn(funcBModule, 'funcB');
spy.mockReturnValue('mocked');
expect(funcA()).toBe('mocked'); // Success!
spy.mockRestore();
});
});
将模块导入自身
"ES6 modules support cyclic dependencies automatically",因此将模块import
嵌入自身是完全有效的,以便该模块中的功能可以为该模块中的其他功能调用 module export :>
helper.js
import * as helper from './helper';
export const funcA = () => {
return helper.funcB();
};
export const funcB = () => {
return 'original';
};
helper.spec.js
import * as helper from './helper';
describe('helper', () => {
test('test funcB', () => {
expect(helper.funcB()).toBe('original'); // Success!
});
test('test funcA', () => {
const spy = jest.spyOn(helper, 'funcB');
spy.mockReturnValue('mocked');
expect(helper.funcA()).toBe('mocked'); // Success!
spy.mockRestore();
});
});
答案 1 :(得分:2)
最新答案,但是应该可以。 另外,您应该在自己的文件中而不是在“帮助程序”测试中测试funcB。
import { funcB } from './funcB';
import { funcA } from './helper';
jest.mock('./funcB');
describe('helper', () => {
test('test funcA', () => {
const funcBSpy = jest.fn();
funcB.mockImplementation(() => funcBSpy());
expect(funcBSpy).toHaveBeenCalledTimes(1);
});
});
答案 2 :(得分:1)
我认为这可能有效
import * as helper from 'helper';
describe('helper', () => {
test('testFuncB', () => {
}
test('testFuncA', () => {
const mockTestFuncB = jest.mock();
// spy on calls to testFuncB and respond with a mock function
jest.spyOn(helper, 'testFuncB').mockImplementationOnce(mockTestFuncB);
// Do the testing ...
// Restore helper.testFuncB to it's original function
helper.testFuncB.mockRestore();
}
}
答案 3 :(得分:1)
import * as helper from 'helper';
describe('helper', () => {
it('should test testFuncA', () => {
const mockTestFuncB = jest.mock();
// spy on calls to testFuncB and respond with a mock function
mockTestFuncB.spyOn(helper, 'testFuncB').mockReturnValue(/*your expected return value*/);
// test logic
// Restore helper.testFuncB to it's original function
helper.testFuncB.mockRestore();
}
}
答案 4 :(得分:1)
我创建了一种名称空间来处理此问题:
let helper = {}
const funcA = (key) => {
return helper.funcB(key)
};
const funcB = (key,prop) => {
return someObj;
};
helper = { funcA, funcB }
module.exports = helper
然后通过jest.fn
答案 5 :(得分:1)
您可以在测试 funcA
时执行以下技巧:
1.模拟funcB
:
helper.funcB = jest.fn().mockImplementationOnce(() => <your data>);
2.将funcB(key)
更改为this.funcB(key)
我遇到了同样的问题并且工作了!完整代码:
export const funcA = (key) => {
return this.funcB(key)
};
export const funcB = (key,prop) => {
return someObj;
};
测试代码:
import helper from 'helper';
describe('helper', () => {
test('testFuncB', () => {
...
}
test('testFuncA', () => {
helper.funcB = jest.fn().mockImplementationOnce(() => <your data>);
}
}
答案 6 :(得分:0)
您可以使用 babel-plugin-rewire 提供的 __set__
函数来模拟内部函数。
假设你已经设置了 babel-plugin-rewire。
helper.spec.js
import {funcA, __set__} as helper from './helper';
describe('helper', () => {
test('test funcA', () => {
__set__('funcB', () => {
return 'funcB return value'
})
expect(funcA()).toBe('funcB return value');
});
});
此解决方案的一个优点是您无需更改任何原始代码