Skip to content

Instantly share code, notes, and snippets.

@rikumi
Created November 9, 2020 08:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rikumi/62c21675b5c6861926e28e2d7b1709f3 to your computer and use it in GitHub Desktop.
Save rikumi/62c21675b5c6861926e28e2d7b1709f3 to your computer and use it in GitHub Desktop.
Jest Moebius
/**
* 生成莫比乌斯对象
* - 生成的对象支持调用,支持属性存取,支持数学运算,支持 await
* - 生成的对象是一个 jest.fn(),可以正常取 mock,可以正常 expect
* - 可以通过传入对象,自定义一些属性的值/实现
* - 从莫比乌斯对象中取出和返回的值默认都是新的莫比乌斯对象,重复取出的同名对象相等
* @param {any} extensions
* @return {any}
*/
const createMoebius = (extensions = {}) => {
return new Proxy(jest.fn(() => createMoebius()), {
get(target, key) {
// 兼容 toString
if (key === 'toString') {
return () => 'MOEBIUS_OBJECT';
}
// 兼容 valueOf,支持四则运算
if (key === 'valueOf') {
return () => 42;
}
// 兼容 await,防止被鸭子类型判断当作 Promise 导致死等
if (key === 'then') {
return undefined;
}
// 避免被 jest 判断为 spy 导致 toBeCalledWith 判断出错
// https://github.com/facebook/jest/blob/4f84f6/packages/expect/src/spyMatchers.ts#L1150
if (key === 'calls') {
return undefined;
}
// 兼容 mock function 中本来的字段,例如 mock
if (key in target || typeof key !== 'string') {
return target[key];
}
// 根据传入的对象增加定制化的属性
if (key in extensions) {
return extensions[key];
}
// 其他情况下创建新的莫比乌斯对象,并保存下来,下次再取同一个 key,要得到同一个 value
return target[key] = createMoebius();
},
set(target, key, value) {
target[key] = value;
return true;
},
});
};
module.exports = createMoebius;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment