테스트 코드에서 mock으로 처리하는 경우1
- Mocking React custom hook with Jest - Stack Overflow
- mrbenhowl/mocking-firebase-initializeApp-and-firebase-auth-using-jest
- Avoid Nesting when you’re Testing
Footnotes
-
그래서 내가 내린 결론은 저렇게 까지는 테스트할 필요가 없고 오히려 애매하게 결합된 컴포넌트들을 분리해서 관리하는게 맞을 것 같다는 생각을 해봤다. ↩
Vitest/Jest Fake Timers로 시간 제어
describe('time-dependent tests', () => {
beforeEach(() => {
vi.useFakeTimers() // jest.useFakeTimers('modern')
})
afterEach(() => {
vi.useRealTimers() // jest.useRealTimers()
})
it('특정 시간에 동작 확인', () => {
vi.setSystemTime(new Date(2000, 1, 1, 13)) // 13시 설정
expect(purchase()).toEqual({ message: 'Success' })
})
it('영업시간 외 동작', () => {
vi.setSystemTime(new Date(2000, 1, 1, 19)) // 19시 설정
expect(purchase()).toEqual({ message: 'Error' })
})
})
@sinonjs/fake-timers 기반. Date, setTimeout 등 모킹.
ResizeObserver Mock (Vitest, ES Module 환경)
vi.hoisted()로 모킹 함수 미리 선언 후 vi.mock()에서 사용:
import { vi } from 'vitest'
const { mockResizeObserver, MockResizeObserver } = vi.hoisted(() => {
let observers: { callback: ResizeObserverCallback; observer: any }[] = []
const MockResizeObserver = vi.fn().mockImplementation((callback) => {
const observer = {
observe: vi.fn(),
unobserve: vi.fn(),
disconnect: vi.fn(),
}
observers.push({ callback, observer })
return observer
})
return {
MockResizeObserver,
mockResizeObserver: {
triggerResize: (entries: ResizeObserverEntry[], index = 0) => {
observers[index]?.callback(entries, observers[index].observer)
},
reset: () => {
observers = []
},
},
}
})
vi.mock('resize-observer-polyfill', () => ({ default: MockResizeObserver }))
// 테스트에서 사용
beforeEach(() => mockResizeObserver.reset())
it('should handle resize', () => {
const mockEntry = {
target: document.createElement('div'),
contentRect: { width: 100 },
}
mockResizeObserver.triggerResize([mockEntry])
})
핵심: ES Module에서는 vi.hoisted() 필수. 여러 observer는 배열로 추적.
Vitest 모킹: vi.mocked() vs vi.hoisted()
vi.mocked()는 타입만 제공, 실제 모킹 구현체는 별도로 필요.
// ❌ mockImplementation이 undefined
const mockUseSize = vi.mocked(useSize)
// ✅ vi.hoisted() 사용 (추천)
const mockUseSize = vi.hoisted(() => vi.fn())
vi.mock('ahooks', () => ({ useSize: mockUseSize }))
beforeEach(() => {
mockUseSize.mockImplementation(() => ({ width: 100, height: 20 }))
})
DOM 속성 모킹 (scrollWidth/clientWidth):
beforeEach(() => {
Object.defineProperty(HTMLElement.prototype, 'scrollWidth', {
configurable: true,
get() {
return 150
},
})
})
afterEach(() => {
// 원래 속성 복원
})
DOM 측정이 복잡하면 Playwright/Cypress로 통합 테스트 고려.
서비스워커로 fetch를 감지해서 해당 기능을 구현한다는 내용. 개인적으로는 mock은 간단하게 구현 가능할 것 같은데 이미 같은 기능의 잘 만들어진 라이브러리들이 있으니까 아이디어 정도로 생각하면 될 것 같다.
addEventListener('fetch', e => {
// e.request
// e.respondWith
})