提问人:Daniel 提问时间:11/1/2023 更新时间:11/1/2023 访问量:22
在单元测试中反应反应值
React reactive values in unit tests
问:
我正在尝试使用“React 上下文依赖注入”对 react 钩子进行单元测试,以便能够更好地应用测试驱动开发(在阅读了两篇关于它的帖子后 https://blog.testdouble.com/posts/2021-03-19-react-context-for-dependency-injection-not-state/ 和 https://medium.com/@matthill8286/dependency-injection-in-react-a-good-guide-with-code-examples-4afc8adc6cdb)。
现在我想伪造/模拟一个钩子的反应性返回值,以便测试另一个钩子并验证它是否对其依赖项的变化做出反应。我准备了一个堆栈闪电战示例:https://stackblitz.com/edit/vitejs-vite-nwro2m?file=src%2FUseUsername.ts
// DependencyContext.ts
import { createContext } from 'react';
export interface Dependencies {
useUserId: () => string;
}
export const DependencyContext = createContext<Dependencies>(null!);
我要测试的钩子是用工厂创建的,以便注入一些预配置的函数,该函数将用户名返回给给定的 userId。它还使用从 DependencyContext 返回。useUserId
// UseUsername.ts
import { useContext } from 'react';
import { DependencyContext } from './DependencyContext';
export function createUseUsername(userNameApi: (userId: string) => string) {
return function () {
const { useUserId } = useContext(DependencyContext);
const userId = useUserId();
return userNameApi(userId);
};
}
使用工厂和 DependencyContext 可以包含测试,隔离钩子,并且不需要模拟模块。 在下面的测试中,我想验证钩子在 userId 更改时是否更新其值。
// UseUsername.test.tsx
import { describe, test, expect } from 'vitest';
import { renderHook, act } from '@testing-library/react';
import { createUseUsername } from './UseUsername';
import { DependencyContext } from './DependencyContext';
describe('UseUsername', () => {
test('it returns correct name for a given userId', () => {
function usernameApiFake(userId: string): string {
const users: Record<string, string> = {
userA: 'usernameA',
userB: 'usernameB',
};
return users[userId] ?? '';
}
let userId = 'userA';
const useUserIdFake = () => userId;
const { result, rerender } = renderHook(
createUseUsername(usernameApiFake),
{
wrapper: ({ children }) => (
<DependencyContext.Provider value={{ useUserId: useUserIdFake }}>
{children}
</DependencyContext.Provider>
),
}
);
expect(result.current).toBe('usernameA');
act(() => (userId = 'userB'));
rerender(); // I don't want to have to call a rerender
expect(result.current).toBe('usernameB');
});
});
问题是钩子不会更新,如果我更改.我必须显式地重新渲染钩子。
我的问题:userId
- 有没有办法使反应式,以便在更改时渲染的钩子自动重新渲染?
userId
userId
- 还是显式调用等效且足以对这个钩子进行单元测试?
rerender
答: 暂无答案
评论