Search code examples
reactjstestingjestjsmockingvitest

Vitest - Mock React Component only in one test


I want to mock a Component named Child in Parent. All tests should use the original Child component except one test should use a Mock. how do I achieve that?

I tried working with

vi.mock('./path/to/child.tsx', async (importActual) => ({
    ...(await importActual<typeof import('./path/to/child.tsx')>()),
    Child: vi.fn()
}));

but I cannot figure out how to mock with the actual implementation for one test and return a mock for another test.


Solution

  • Using spy on components works as well and is perfect for mocking a component for only one test.

    I found this in the documentation: https://vitest.dev/guide/mocking.html#cheat-sheet

    Example with vi.spyOn:

    import * as exports from './some-path.js'
    
    vi.spyOn(exports, 'SomeClass').mockImplementation(() => {
        // whatever suites you from first two examples
    })
    

    and tried with mocking a component like so:

     import * as childComponent from './path/to/child.tsx'
    
     describe('Parent', () => {
          it('tests with mocked child', () => {
               vi.spyOn(childComponent, 'Child').mockImplementation((props: ChildProps) => {
                    return (
                         <div>
                              // your component mock able to use component props as well
                         </div>
                    )
          })
     })
    

    other sources which might be helpful but didn't resolve my specific case:

    Using different mocks for different tests:

    https://github.com/vitest-dev/vitest/discussions/3589#discussioncomment-6195214

    import { namedExport } from './path/to/module.js'
    
    const mocks = vi.hoisted(() => {
        return {
            namedExport: vi.fn(),
        }
    })
    
    vi.mock('./path/to/module.js', () => {
        return {
            namedExport: mocks.namedExport,
        }
    })
    
    it('test 1', () => {
        mocks.namedExports.mockReturned(true)
        // some test
    })
    
    it('test 2', () => {
        mocks.namedExports.mockReturned(false)
        // some test
    })
    

    and this one: https://github.com/vitest-dev/vitest/discussions/4328