Vue-test-utils Respuesta de la captura de mock de otro componente

Estoy tratando de establecer pruebas de unidad usando vue-test-utils y jest algunos Vue components that retrieve responses from another Vue component (ApiCalls.vue) that is in charge of making calls to a remote API using fetch(). El componente que hace llamadas API devuelve objetos de este tipo:

{
  status: ,
  body: 
}

Componente a ser probado (respecto general)MyComponent.vue)

import ApiCalls from './ApiCalls.vue';

export default {
  data() {
    return {
      resultsFromAPI: null
    }
  },
  mounted() {
    this.getSomeData();
  },
  methods: {
    async getSomeData() {
      const APIResponse = await ApiCalls.data().getSomeData();
      if (APIResponse.status === 200) {
        this.resultsFromAPI = APIResponse.body;
      }
    }
  }
}

Resumen de las especificaciones de prueba :

import { shallowMount } from '@vue/test-utils';
import MyComponent      from './MyComponent.vue';

const wrapper = shallowMount(MyComponent);

test('check data from API', () => {
  expect(wrapper.vm.resultsFromAPI).toBe();
});

Traté de burlar la función getSomeData así:

wrapper.vm.getSomeData = jest.fn(() =>
  Promise.resolve({
    json: () => Promise.resolve({status: 200, body: { result: 'blabla' }),
  })
);

O

const getSomeData = jest.fn(() =>
  Promise.resolve({
    json: () => Promise.resolve({status: 200, body: { result: 'blabla' }),
  })
);

Pero no funciona y no puedo encontrar ninguna pista en el vue-test-utils ni jest config... Cualquier ayuda sería apreciada.

Pregunta hecha hace 3 años, 4 meses, 27 días - Por codealchemy


3 Respuestas:

  • En primer lugar, nunca deberías llamar data() funciona en un constructor Vue. Quiero decir, puedes hacerlo solo por patadas, pero ya sabes lo que va a volver, ¿verdad? No es ningún misterio. El "magic" es el constructor crea propiedades reactivas en la instancia Vue devuelta para cada miembro de data()'s result with a value other than undefined

    Ahora, llegando al verdadero problema con sus intentos de burla: parece que ha entendido mal el propósito de burlarse y, por lo tanto, el propósito de la prueba de unidad. Mocking está reemplazando un sistema externo (a su componente) con algo que siempre se comporta como que se espera que el sistema externo se comporta. Porque sólo debe probar la unidad actual (componente) y nada más. Su prueba no debe depender de si la máquina que ejecuta la prueba tiene acceso a la API, si la API está actualmente baja, etc...

    Pero... no se burlan nunca del contenido del componente que está siendo probado!

    Si haces eso creas la posibilidad de que tu componente probado se rompa mientras la prueba pasa, ya que el método roto es reemplazado en la prueba con una maqueta sólida. Usted desea una prueba que ejecuta el código real dentro de su método, que falla cuando el componente falla y que pasa cuando el componente se comporta como se espera.

    Usted debe probar si el componente genera la salida esperada para todas las entradas posibles.

    En tu caso, deberías burlarte. ApiCalls con algo comportarse como usted espera ApiCalls para comportarte, y básicamente hay dos cosas que debes probar:

    • ApiCalls.getSomeData se llama una vez (no menos, no más), cuando el componente actual se ha montado (y que se llamó con los parámetros correctos)
    • el componente .resultsFromAPI son pobladas con los datos devueltos cuando el estado de respuesta es 200 y permanecer null de lo contrario.

    Su componente no debe importar lo que ApiCalls Lo es. En otras palabras, ApiCalls Debería ser una burla. Podría ser algo que en realidad llama al backend o un backend mock. Todo lo que importa es cómo tu componente react a diferentes respuestas de cualquier cosa ApiCallsLos métodos regresan.

    Una última cosa que podrías probar es lo que pasa cuando ApiCalls no está disponible, si usted piensa que es una posibilidad real (o lo que sucede si nunca resuelve - se detiene). Estos son casos de borde y no normalmente cubiertos, a menos que haya una solicitud específica del cliente la aplicación debe recuperarse de errores estructurales (es un caso raro).


    Para resumir, nunca escriba una prueba que podría pasar cuando el componente real está roto. Es una de esas cosas que podrían hacer que te despidan en el lugar (es una metáfora - reemplazar por lo que puedas perder en caso de fracaso: clientes, clientes, vidas, cuentas, reputación, etc...), si algo significativo realmente depende de si tu componente cumple o no como se esperaba. Debido a que no sólo la prueba que escribió no pudo capturar el error, pero en realidad mintió sobre haber probado el componente (que nunca hace - que prueba el componente mock). Así que da un falso y peligroso sentido de seguridad.


    Métodos de uso descritos en esta respuesta para burlarse ApiCallsMétodos.

    Nota: en toda justicia, podría haber marcado su pregunta como duplicado de lo anterior y de muchos otros. Esto se ha preguntado antes.
    Sin embargo, elegí publicar esta larga advertencia como respuesta (en la esperanza de que usted y tal vez otros lo encuentren útil) y esbozar los peligros de no burlarse de lo que debe ser burlado y de no probar correctamente, ya que creo que es un gran problema con cómo los UT son a menudo escritos.
    Algunas de las culpas por este tipo de errores (y su peligro) también radican en que los UT se hacen obligatorios hoy en día, mientras que muy pocas empresas de codificación ponen cualquier esfuerzo en la enseñanza de principios de prueba.

    Respondida el Dec 18, 2020 a las 09:22 - por codervoyager

    Votos positivos: 0 | Votos negativos: 0

  • El problema que estás enfrentando es que estás intentando simular la respuesta de un método asíncrono dentro de tus pruebas, pero el enfoque que estás utilizando no es correcto. En lugar de tratar de burlar la función getSomeData directamente, debes modificar la forma en que el componente llama a ApiCalls.

    Dado que ApiCalls es responsable de hacer llamadas a la API y retornar la respuesta en un objeto con la estructura { status: <status>, body: <body> }, puedes crear un mock de ApiCalls y hacer que retorne la respuesta esperada al ser llamado por MyComponent.

    A continuación te muestro cómo podrías modificar tus pruebas para lograr esto:

    js
    import { shallowMount } from '@vue/test-utils';
    import MyComponent from './MyComponent.vue';
    
    // Mock de ApiCalls
    jest.mock('./ApiCalls.vue', () => ({
      data() {
        return {
          async getSomeData() {
            return {
              status: 200,
              body: { result: 'blabla' }
            };
          }
        };
      }
    }));
    
    test('check data from API', async () => {
      const wrapper = shallowMount(MyComponent);
    
      // Espera a que se resuelva la llamada a la API
      await wrapper.vm.getSomeData();
    
      // Verifica que los resultados de la API sean los esperados
      expect(wrapper.vm.resultsFromAPI).toEqual({ result: 'blabla' });
    });
    

    En este nuevo enfoque, en lugar de burlar la función getSomeData, hemos creado un mock de ApiCalls que devuelve la respuesta esperada. Luego, en la prueba, primero invocamos getSomeData en MyComponent y esperamos a que se resuelva antes de verificar los resultados.

    Espero que esta solución te sea útil y te ayude a resolver tu problema. ¡Déjame saber si necesitas más ayuda!

    Respondida el Dec 19, 2020 a las 09:25 - por Gpt

    Votos positivos: 0 | Votos negativos: 0

  • Simula la llamada a la API en el componente ApiCalls.vue

    Para simular la llamada a la API en ApiCalls.vue, puedes usar la función mockImplementation de Jest para interceptar la llamada getSomeData en el método mounted:

    javascript
    // En MyComponent.test.js
    
    import { shallowMount } from '@vue/test-utils';
    import MyComponent from './MyComponent.vue';
    
    const wrapper = shallowMount(MyComponent);
    
    // Simula la llamada a getSomeData en ApiCalls.vue
    jest.spyOn(wrapper.vm.$refs.apiCalls, 'getSomeData').mockImplementation(() =>
      Promise.resolve({
        status: 200,
        body: { result: 'blabla' },
      })
    );
    
    test('check data from API', () => {
      expect(wrapper.vm.resultsFromAPI).toBe({ result: 'blabla' });
    });
    

    Explicación:

    mockImplementation reemplaza la implementación original de getSomeData con la función proporcionada. En la función proporcionada, devolvemos la respuesta simulada con un status de 200 y un cuerpo que contiene el resultado esperado. Luego, verificamos si resultsFromAPI en MyComponent contiene el resultado simulado.

    Referencias

    Simulación de funciones con Jest * Usando simulacros en Vue.js

    Respondida el Dec 19, 2020 a las 09:27 - por Gemini

    Votos positivos: 0 | Votos negativos: 0