我有以下(示例)组件,我试图将其模拟为集成测试的一部分。
interface MyComponentProps { acceptableRoles: string[]}
export default class MyComponent extends Component<React.PropsWithChildren<MyComponentProps>> {
public canRender(currentRoles: string[]): boolean {
// determine if any current roles intersect with acceptableRoles
}
public render() {
return (
<MyContext.Consumer>
{(roles) => this.canRender(roles)
? this.props.children
: null
}
</MyContext.Consumer>
}
}
我想模拟
render()
的输出以删除 <MyContext.Consumer>
包装器并将 roles
传递到我的模拟中。
当在我正在测试的组件中使用时,上面的组件很简单
<MyComponent acceptableRoles={"role1", "role2"}>
<div>Show this if allowed</div>
</MyComponent>
我尝试了很多事情,这感觉是我能得到的最接近的;但是,我收到一条错误消息,指出
origin.canRender is not a function
。当我检查它时,它是未定义的。
const myTestRoles = ["role3", "role4"]; //changes within different tests
jest.mock("./MyComponent", () => (props: any) => {
const origin = jest.requireActual<MyComponent>("./MyComponent");
// console.info("Origin: " + origin.canRender); //Outputs as "Origin: undefined"
return <div>{
origin.canRender(_user)
? props.children
: null}
</div>;
});
一切都“有效”,直到我添加对“origin.canRender”的调用,它提供了“不是函数”错误。
我知道严格的单元测试,我会用显式模拟跳过这个调用,但这让我真的想知道是否可以做到这一点。
是否可以从模拟方法中调用这样的实例方法?
由于您使用的是
export default MyComponent
,因此 jest.requireActual('./MyComponent')
语句将返回 { default: [class MyComponent extends Component] }
。
您可以通过 JavaScript 类的
.prototype
属性访问其公共方法。
例如
MyComponent.tsx
:
import React, { Component } from 'react';
const MyContext = React.createContext<string[]>([]);
interface MyComponentProps {
acceptableRoles: string[];
}
export default class MyComponent extends Component<React.PropsWithChildren<MyComponentProps>> {
public canRender(currentRoles: string[]): boolean {
return true;
}
public render() {
return <MyContext.Consumer>{(roles) => (this.canRender(roles) ? this.props.children : null)}</MyContext.Consumer>;
}
}
index.test.tsx
:
import React from 'react';
import { render, screen } from '@testing-library/react';
import MyComponent from './MyComponent';
jest.mock('./MyComponent', () => (props: any) => {
const origin = jest.requireActual('./MyComponent');
console.log("🚀 ~ jest.mock ~ origin:", origin)
console.info('Origin: ', origin.default.prototype.canRender);
return <div>{origin.default.prototype.canRender(['role3']) ? props.children : null}</div>;
});
describe('78269182', () => {
test('should pass', () => {
render(
<MyComponent acceptableRoles={['role1', 'role2']}>
<div>Show this if allowed</div>
</MyComponent>,
);
screen.debug();
});
});
测试结果:
console.log
🚀 ~ jest.mock ~ origin: { default: [class MyComponent extends Component] }
at log (stackoverflow/78269182/index.test.tsx:7:11)
console.info
Origin: [Function: canRender]
at info (stackoverflow/78269182/index.test.tsx:8:11)
console.log
<body>
<div>
<div>
<div>
Show this if allowed
</div>
</div>
</div>
</body>
at logDOM (node_modules/@testing-library/dom/dist/pretty-dom.js:87:13)
PASS stackoverflow/78269182/index.test.tsx
78269182
√ should pass (40 ms)
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 1.086 s
Ran all test suites related to changed files.
封装版本:
"jest": "^29.7.0"