测试 React 上下文提供程序
简要背景:我被要求修改一个名为 ` <ContextProvider><AuthProvider /> ` 的现有上下文提供程序及其关联的上下文AuthContext。
没有测试用例。因此,我决定在进行任何操作之前先编写一些测试用例。
我当时就在想,我该如何测试上下文提供程序呢🤔?
我们来做个白板讨论:
- 上下文提供程序是一个组件……
render(
<MyContextProvider />
);
- 包含子元素……
render(
<MyContextProvider>
<Child />
</MyContextProvider>
);
- ……它可以访问上下文提供程序提供的值。
render(
<MyContextProvider>
<Child /> /* test that Child may access the expected value */
</MyContextProvider>,
);
太棒了!我们可以把它转换成更实际的代码!
$> touch src/contexts/auth-context.test.js
import { render } from '@testing-library/react';
import AuthContext, { AuthProvider } from './auth-context';
describe('<AuthProvider />', () => {
test('provides expected AuthContext obj to child elements', () => {
render(
<AuthContext>
< ?? />
</AuthContext>,
);
// expect()
}
})
我们在这里取得了进展👩⚕️。
接下来,我们将测试上下文和提供程序组件(我省略了我们项目的具体细节)。
const AuthContext = createContext<{
user?: AuthUser | undefined;
isAdmin?: boolean;
}>({});
export function AuthProvider({ children }: Props): JSX.Element {
const [user, setUser] = useState<AuthUser | undefined>();
useEffect(() => {
/* API calls */
setUser( ... )
}, []);
const isAdmin = () => /* some logic */
return (
<AuthContext.Provider value={{ user, isAdmin: isAdmin() }}>
{children}
</AuthContext.Provider>
);
}
export default AuthContext;
好的,我们确实想测试子元素是否可以{user, isAdmin}使用类似这样的方法访问这些值React.useContext():
const TestingComponent = () => {
const { user, isAdmin } = useContext(AuthContext);
return (
<>
<p>{user?.name}</p>
<p>{isAdmin?.toString()}</p>
</>
);
};
这似乎就是缺失的那一块:
import { render } from '@testing-library/react';
import AuthContext, { AuthProvider } from './auth-context';
+
+ const TestingComponent = () => {
+ const { user, isAdmin } = useContext(AuthContext);
+ return (
+ <>
+ <p>{user?.name}</p>
+ <p>{isAdmin?.toString()}</p>
+ </>
+ );
+};
+
describe('<AuthProvider />', () => {
test('provides expected AuthContext to child elements', () => {
render(
<AuthContext>
- < ?? />
+ <TestingComponent />
</AuthContext>,
);
- // expect()
+ // expected name
+ // expected isAdmin
}
})
现在我们已经有了所有部件;AuthContext获取用户并发出一些 HTTP 请求,然后公开用户 + 一个已处理的属性(isAdmin)。
我们针对此React 上下文提供程序的最终单元测试如下所示。(我省略了与模拟 API 相关的代码行,这些代码行取决于您使用的请求库。)
import { render } from '@testing-library/react';
import AuthContext, { AuthProvider } from './auth-context';
const TestingComponent = () => {
const { user, isAdmin } = useContext(AuthContext);
return (
<>
<p>{user?.name}</p>
<p>{isAdmin?.toString()}</p>
</>
);
};
const regularUser = {
name: 'Jhon Doe',
/* fields that resolve as not admin */
};
const adminUser = {
name: 'Jane Doe',
/* fields that resolve as admin user */
};
describe('<AuthProvider />', () => {
test('provides expected AuthContext to child elements', () => {
[
{
scenario: 'regular user',
user: regularUser,
expectedName: 'Jhon Doe',
expectedAdmin: 'false',
},
{
scenario: 'admin user',
user: adminUser,
expectedName: 'Jane Doe',
expectedAdmin: 'true',
}
].forEach(({ scenario, user, expectedName, expectedAdmin }) => {
test(scenario, () => {
/* mock the HTTP request */
const { getByTestId } = render(
<AuthProvider>
<TestingComponent />
</AuthProvider>,
);
const userName = getByTestId('user-name');
const isAdminValue = getByTestId('is-admin');
expect(userName.textContent).toEqual(expectedName);
expect(isAdminValue.textContent).toEqual(expectedAdmin);
});
});
});
横幅图片:Storyset 提供的教育插图
感谢阅读💚。
文章来源:https://dev.to/manuartero/testing-a-react-context-provider-5cfg