Open SoYoung210 opened 4 years ago
custom hook에서 두 가지 이상의 테스트를 작성할 때 mocking 값이 변하지 않던 기이한 현상
개별적으로 하나씩 run시키면 모두 성공하나, 두개를 같이 돌릴 경우 실패
#### Custom hooks ```ts // Custom hooks import useSWR from 'swr'; import { getDataSample, SomeData } from '@/api/someData; export const useSomeData = () => { const { data } = useSWR( 'keySample', getDataSample, { suspense: true }, ); return data?.map(value => ({ ...card, testValue: value.sample === '0', })); }; ``` #### mocking Target Function ```ts export const getDataSample = (): Promise => { // mockData with delay return new Promise(resolve => setTimeout(() => resolve(mockValue), 800)); }; ``` #### Test Code ```ts // test code describe('useSomeData', () => { afterEach(cleanup); test('test1', async () => { getDataSampleAPI.mockResolvedValueOnce([{ ...mockRankingCard, testValue: '0', }]); const { result } = renderHook(useSomeData); await act(() => { return new Promise(res => setTimeout(res, 900)); }); console.log('@@@@ first res', (result.current as any)[0].testValue); expect((result.current as any)[0].isInPromotion).toBe(true); }); test('test2', async () => { getDataSampleAPI.mockResolvedValueOnce([{ ...mockRankingCard, testValue: '10', }]); const { result } = renderHook(useSomeData); await act(() => { return new Promise(res => setTimeout(res, 900)); }); console.log('@@@@ second res', (result.current as any)[0].testValue); expect((result.current as any)[0].isInPromotion).toBe(true); }); }); ```
console.log('@@@@ second res', (result.current as any)[0].testValue);값이 바뀌지 않았다. (첫번째 테스트 값에 의존적)
console.log('@@@@ second res', (result.current as any)[0].testValue);
Jest mock혹은 renderHook에서의 문제를 의심해보았지만 범인은 타이머
renderHook
jest.useFakeTimers(); describe('useSomeData', () => { afterEach(cleanup); test('test1', async () => { const { result, waitForValueToChange } = renderHook(useSomeData); await waitForValueToChange(() => { act(() => { jest.runAllTimers(); }); return result.current; }); // 이후 코드 }) test('test2', async () => { const { result, waitForValueToChange } = renderHook(useSomeData); await waitForValueToChange(() => { act(() => { jest.runAllTimers(); }); return result.current; }); // 이후 코드 }) })
timer mocking으로 해결
Jest timer mocks를 참고해서 조사중..
Desc
custom hook에서 두 가지 이상의 테스트를 작성할 때 mocking 값이 변하지 않던 기이한 현상
사용했던 코드들
#### Custom hooks ```ts // Custom hooks import useSWR from 'swr'; import { getDataSample, SomeData } from '@/api/someData; export const useSomeData = () => { const { data } = useSWR(
'keySample', getDataSample, { suspense: true },
);
return data?.map(value => ({
...card,
testValue: value.sample === '0',
}));
};
```
#### mocking Target Function
```ts
export const getDataSample = (): Promise => {
// mockData with delay
return new Promise(resolve => setTimeout(() => resolve(mockValue), 800));
};
```
#### Test Code
```ts
// test code
describe('useSomeData', () => {
afterEach(cleanup);
test('test1', async () => {
getDataSampleAPI.mockResolvedValueOnce([{
...mockRankingCard,
testValue: '0',
}]);
const { result } = renderHook(useSomeData);
await act(() => {
return new Promise(res => setTimeout(res, 900));
});
console.log('@@@@ first res', (result.current as any)[0].testValue);
expect((result.current as any)[0].isInPromotion).toBe(true);
});
test('test2', async () => {
getDataSampleAPI.mockResolvedValueOnce([{
...mockRankingCard,
testValue: '10',
}]);
const { result } = renderHook(useSomeData);
await act(() => {
return new Promise(res => setTimeout(res, 900));
});
console.log('@@@@ second res', (result.current as any)[0].testValue);
expect((result.current as any)[0].isInPromotion).toBe(true);
});
});
```
증상
console.log('@@@@ second res', (result.current as any)[0].testValue);
값이 바뀌지 않았다. (첫번째 테스트 값에 의존적)해결
Jest mock혹은
renderHook
에서의 문제를 의심해보았지만 범인은 타이머timer mocking으로 해결
더 자세한 원인
Jest timer mocks를 참고해서 조사중..