Javascript 在React with Jest中使用样式为@material ui创建手动模拟
我正在尝试为Javascript 在React with Jest中使用样式为@material ui创建手动模拟,javascript,reactjs,mocking,jestjs,material-ui,Javascript,Reactjs,Mocking,Jestjs,Material Ui,我正在尝试为@material ui/core/styles模块创建手动模拟,该模块导出名为with styles的HOC 将内联mock与jest.mock结合使用效果很好,但当我尝试将此逻辑移动到sharable\uuuuuumocks\uuuuu文件夹中时,它不再起作用 我从正在测试的文件中删除了所有不必要的代码,只保留了产生问题的两行代码: import { withStyles } from '@material-ui/core/styles'; console.log('loade
@material ui/core/styles
模块创建手动模拟,该模块导出名为with styles
的HOC
将内联mock与jest.mock
结合使用效果很好,但当我尝试将此逻辑移动到sharable\uuuuuumocks\uuuuu
文件夹中时,它不再起作用
我从正在测试的文件中删除了所有不必要的代码,只保留了产生问题的两行代码:
import { withStyles } from '@material-ui/core/styles';
console.log('loaded styles:', withStyles);
export default 'hello';
测试也简化了,只是为了看看模拟是否工作,如下所示:
import test from '../test';
console.log(test);
我尝试的是在项目的根目录中创建一个\uuu mocks\uu
文件夹,其中有节点\u modules
文件夹
在那里,我创建了第一个名为@materialui
的文件夹,并在其中创建了另一个名为core
的文件夹。
在这个文件夹中,我有一个名为styles.js
的文件,其中包含以下代码:
export const withStyles = 'hello world';
所以结构看起来像:
- __mocks__
- @material-ui
- core
- styles.js
- node_modules
这是在同一测试文件中定义模拟的代码:
jest.mock('@material-ui/core/styles', () => ({
withStyles: () => Component => props => (
<Component
classes=""
{...props}
/>
),
}));
在我的测试文件中,它使用real和style
,因此使用real模块。
没有使用任何模拟
如果我使用:
jest.mock('@material-ui/core/styles');
它使用jest自动生成的自动模拟(或者看起来是这样),跳过了我上面定义的模拟
关于软件包,我使用了CRA
来引导应用程序,我目前使用的jest
版本是20,带有react脚本
版本1.0.17
谢谢大家的帮助 以下是您应该如何在
\uuuuuumocks\uuuuu/@material ui/core/styles.js
中使用手动模拟:
// Grab the original exports
import * as Styles from '@material-ui/core/styles';
const mockWithStyles = () => {
console.log('withStyles being mocked'); // this shows that it works
/**
* Note: if you want to mock this return value to be
* different within a test suite then use
* the pattern defined here:
* https://jestjs.io/docs/en/manual-mocks
*/
return () => {}; // your mock function (adjust as needed)
// you can also return the same implementation on certain conditions
// return Styles.makeStyles;
};
module.exports = { ...Styles, withStyles: mockWithStyles };
下面是我如何手动模拟makeStyles
:
// Grab the original exports
// eslint-disable-next-line import/no-extraneous-dependencies
import * as Styles from '@material-ui/core/styles';
import createMuiTheme from '@material-ui/core/styles/createMuiTheme';
import options from '../../../src/themes/options';
const mockMakeStyles = func => {
/**
* Note: if you want to mock this return value to be
* different within a test suite then use
* the pattern defined here:
* https://jestjs.io/docs/en/manual-mocks
*/
/**
* Work around because Shallow rendering does not
* Hook context and some other hook features.
* `makeStyles` accept a function as argument (func)
* and that function accept a theme as argument
* so we can take that same function, passing it as
* parameter to the original makeStyles and
* binding it with our custom theme
*/
const theme = createMuiTheme(options);
return Styles.makeStyles(func.bind(null, theme));
};
module.exports = { ...Styles, makeStyles: mockMakeStyles };
而makeStyles
结果使用React.useContext
,因此我们必须避免对makeStyles
模拟useContext
。如果在组件中首先使用React.useContext(…)
,请使用mockImplementationOnce
,或者在测试代码中过滤掉它,如下所示:
jest.spyOn(React, 'useContext').mockImplementation(context => {
console.log(context);
// only stub the response if
if (context.displayName === 'MyAppContext') {
return {
auth: {},
lang: 'en',
snackbar: () => {},
};
}
const ActualReact = jest.requireActual('react');
return ActualReact.useContext(context);
});
在调用createContext()
时,可能在store.js
中添加displayName
(标准)或任何其他自定义属性来标识上下文:
const store = React.createContext(initialState);
store.displayName = 'MyAppContext';
makeStyles
上下文显示名称将显示为StylesContext
和themeecontext
,它们的实现将保持不变以避免错误
这修复了
makeStyles
的所有模拟问题。但是我没有使用和样式来深入了解它的结构,但是类似的逻辑应该是适用的。我找到了在(\uuuuuumocks\uuuu/@material ui/core/styles.js
)中手动模拟makeStyles的完美方法,方法是使用相同的原始makeStyles绑定一个动态创建的主题。这解决了未定义主题
、测试覆盖率、通过道具
内部makeStyles
函数属性的未覆盖测试的所有问题。如果你仍然想要这个,我会花点时间来回答,因为它还处理jest.spyOn(React,'useContext').mockImplementation(()=>{})
,这会使一些useStyles
崩溃,这些useStyles
也会在内部使用React.useContext
,这类似于withStyles
,但是makeStyles
更适合于Hook,这就是我所使用的。但同样的逻辑也适用。此外,您不应该使用jest.mock(“@materialui/core/styles”)代码>在手动模拟中。在Manual Mock中,您必须返回您想要代替样式的任何内容。例如,您可以只导入所有样式,准备一个withStyles
函数并返回{….Styles.withStyles}
以仅替换withStyles
。
const store = React.createContext(initialState);
store.displayName = 'MyAppContext';