Vitest mockup functions
Tags: react, vite, testing, typescript
Published: 2023-10-15 21:27:17

##Intoducción
Las funciones de simulación (mock) son una herramienta útil para simular el comportamiento de funciones y métodos en pruebas unitarias. Estas funciones imitan la implementación real de una función, pero sin ejecutar su código interno. En vitest, puedes usar la función **vi.mock** para simular un módulo y la función **vi.spyOn** para crear un espía en una función importada.

Si deseas simular una función importada en vitest, puedes usar la función vi.mock. El primer argumento de esta función es la ruta al módulo que se está importando. Si estás utilizando vi.mock para simular un módulo, asegúrate de que no haya variables de nivel superior dentro del archivo, ya que esta llamada se eleva a la parte superior del archivo.

Si estás intentando simular una función importada desde un módulo, puedes usar vi.spyOn para crear un espía en la función importada. Aquí hay un ejemplo:

```
import { expect, vi } from 'vitest'
import * as myModule from './myModule.js'

describe('Mi Suite de Pruebas', () => {
  beforeEach(() => {
    const spy = vi.spyOn(myModule, 'myFunction')
    spy.mockReturnValue('valor simulado')
  })

  it('debería probar myFunction', () => {
    const result = myModule.myFunction()
    expect(result).toBe('valor simulado')
  })
})

```

En este ejemplo, creamos un espía en myFunction usando vi.spyOn. Luego simulamos el valor de retorno de myFunction usando spy.mockReturnValue. Finalmente, probamos que myFunction devuelve el valor simulado usando expect.

Por otro lado en React podemos usarlo de la siguiente manera.

###Componente

```
import './AccountWidget.scss';
import { UserPicture } from '../UserPicture';
import { useAppSelector } from '../../hooks';

const AccountWidget = () => {
	const user = useAppSelector(state => state.user.data);

	return (
		<div className='AccountWidget'>
			<div className="AccountWidget-ownerinfo">
				<UserPicture picture={user?.picture} username={user?.username} />
				<div className='ownerinfo-names'>
					<p className='ownerinfo-username' data-testid='username'>{user?.username}</p>
					<p className='ownerinfo-fullname'>{user?.fullname}</p>
				</div>
			</div>
			<button className='btn-changeaccount' role='button'>Cambiar</button>
		</div>
	);
};

export default AccountWidget;
```

###Test

```
import { cleanup, render, screen } from '@testing-library/react';
import AccountWidget from './AccountWidget';
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
import { BrowserRouter } from 'react-router-dom';
import * as hooks from '../../hooks';

describe('AccountWidget', () => {
  const user = {
    username: 'Furio',
    fullname: 'Roy Andres',
    picture: 'https://test.com/image.jpg'
  }

  afterEach(cleanup)

  beforeEach(() => {
    const spy = vi.spyOn(hooks, 'useAppSelector');
    spy.mockReturnValue(user);
  })

  it('should render user information', () => {
    render(
      <AccountWidget />, { wrapper: BrowserRouter }
    );

    expect(screen.getByTestId('username')).toHaveTextContent(user.username);
    expect(screen.getByText(user.fullname)).toBeInTheDocument();
    expect(screen.getByRole('img')).toHaveAttribute('src', user.picture);
  });

  it('should render a "Cambiar" button', () => {
    render(
      <AccountWidget />, { wrapper: BrowserRouter }
    );

    expect(screen.getByRole('button', { name: 'Cambiar' })).toBeInTheDocument();
  });
});

```

Se definen dos cosas:

La variable user es un objeto que contiene información de ejemplo de un usuario. Este objeto se utiliza más adelante en el test para simular el hook useAppSelector y comprobar que el componente AccountWidget muestra correctamente la información del usuario.

Se utiliza la función beforeEach de vitest para simular el hook useAppSelector y hacer que devuelva el objeto user definido anteriormente. Para ello, se utiliza la función vi.spyOn para crear un mock del módulo hooks que se importa en el componente AccountWidget. Luego, se llama a la función mockReturnValue para simular el hook useAppSelector y hacer que devuelva el objeto user.

En resumen, se encarga de simular el hook useAppSelector para que devuelva un objeto de ejemplo y poder comprobar lo que el componente AccountWidget muestra