在提供的上下文中实现的功能,而不是开玩笑模拟
我需要测试React应用程序中的单击按钮,该按钮调用上下文提供的函数。当调用上下文在嘲笑测试中提供的模拟函数时,调用了实际函数。如何解决这个问题?
应用程序App.TSX
import React, {useContext, useState} from 'react'
import styles from './App.module.scss'
import {ThemeContext} from './context/theme/ThemeProvider'
export const App = (): JSX.Element => {
const {changeTheme, activeTheme} = useContext(ThemeContext)
const [theme, setTheme] = useState<string>(activeTheme)
const setNewTheme = (newTheme: string) => {
changeTheme(newTheme)
setTheme(newTheme)
}
return (
<div className={styles.container}>
<h1>Project Name</h1>
<button
data-testid='app-theme-btn1'
onClick={() => {
setNewTheme('dark')
}}
>
Click here
</button>
<p>{`Active Theme: ${theme}`}</p>
</div>
)
}
实际测试
test('click button changes theme', async () => {
const defaultTheme = 'light'
type ThemeContext = {
activeTheme: string
changeTheme: (theme: string) => void
}
const defaultThemeContext: ThemeContext = {
activeTheme: defaultTheme,
changeTheme: (theme) => {
/* left empty */
}
}
const ThemeContext = createContext<ThemeContext>(defaultThemeContext)
const themeContext = {
activeTheme: defaultTheme,
changeTheme: jest.fn().mockImplementation((newTheme) => {
themeContext.activeTheme = newTheme
})
}
render(
<ThemeContext.Provider value={themeContext}>
<App />
</ThemeContext.Provider>
)
screen.debug(undefined, Infinity)
const themeButton = screen.getByTestId('app-theme-btn1')
await userEvent.click(themeButton)
await waitFor(() => screen.queryByText('Active Theme: dark'))
// Error: expect(jest.fn()).toHaveBeenCalledTimes(expected)
//
// Expected number of calls: 1
// Received number of calls: 0
expect(themeContext.changeTheme).toHaveBeenCalledTimes(1)
screen.debug(undefined, Infinity)
})
I need to test the click on a button in a React application which invokes a function provided by the context. When invoking the mocked function provided by the context in a Jest test the actual function is called. What to do to resolve this ?
Application App.tsx
import React, {useContext, useState} from 'react'
import styles from './App.module.scss'
import {ThemeContext} from './context/theme/ThemeProvider'
export const App = (): JSX.Element => {
const {changeTheme, activeTheme} = useContext(ThemeContext)
const [theme, setTheme] = useState<string>(activeTheme)
const setNewTheme = (newTheme: string) => {
changeTheme(newTheme)
setTheme(newTheme)
}
return (
<div className={styles.container}>
<h1>Project Name</h1>
<button
data-testid='app-theme-btn1'
onClick={() => {
setNewTheme('dark')
}}
>
Click here
</button>
<p>{`Active Theme: ${theme}`}</p>
</div>
)
}
Actual test
test('click button changes theme', async () => {
const defaultTheme = 'light'
type ThemeContext = {
activeTheme: string
changeTheme: (theme: string) => void
}
const defaultThemeContext: ThemeContext = {
activeTheme: defaultTheme,
changeTheme: (theme) => {
/* left empty */
}
}
const ThemeContext = createContext<ThemeContext>(defaultThemeContext)
const themeContext = {
activeTheme: defaultTheme,
changeTheme: jest.fn().mockImplementation((newTheme) => {
themeContext.activeTheme = newTheme
})
}
render(
<ThemeContext.Provider value={themeContext}>
<App />
</ThemeContext.Provider>
)
screen.debug(undefined, Infinity)
const themeButton = screen.getByTestId('app-theme-btn1')
await userEvent.click(themeButton)
await waitFor(() => screen.queryByText('Active Theme: dark'))
// Error: expect(jest.fn()).toHaveBeenCalledTimes(expected)
//
// Expected number of calls: 1
// Received number of calls: 0
expect(themeContext.changeTheme).toHaveBeenCalledTimes(1)
screen.debug(undefined, Infinity)
})
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
问题是您在测试案例中创建不同的反应上下文,而不是使用
./
./ context/themey/theaprovider 模块中创建的
themecontext
。换句话说,
usecontext()
app
组件中使用的上下文应为themeContext
,以便app
组件可以接收上下文值并订阅从themecontext.provider
的值更改。例如
app.tsx
:theme-provider.tsx
:app.test.tsx
:测试结果:
The problem is you create a different React context in the test case rather than using the
ThemeContext
created in./context/theme/ThemeProvider
module.In other words, the context used by
useContext()
hook in theApp
component should be theThemeContext
so thatApp
component can receive the context value and subscribe to the value changes fromThemeContext.Provider
.E.g.
app.tsx
:theme-provider.tsx
:app.test.tsx
:Test result: