Cuándo “desenchufar” un componente en una prueba unitaria de Vue.js

Para probar un componente de forma aislada, puede reemplazar sus componentes secundarios aplicándolos. Vue Test Utils puede hacer esto automáticamente por usted con una característica llamada shallowMount.

Pero, ¿qué sucede si un componente está estrechamente acoplado a uno de sus hijos? Todavía puedes usar shallowMountpero luego tendrá que “desconectar” selectivamente al niño estrechamente acoplado.

En este artículo, le mostraré cómo usar el stubing para escribir pruebas unitarias más simples.

Nota: este artículo fue publicado originalmente aquí en el blog de desarrolladores de Vue.js el 30/09/2019.

Pruebas en aislamiento

Una idea clave de las pruebas unitarias es probar una “unidad” de la aplicación de forma aislada. En las aplicaciones frontend basadas en componentes, consideramos que la “unidad” es un componente.

Probar un componente de forma aislada garantiza que las pruebas no se vean afectadas por las dependencias y otras influencias de los componentes secundarios.

Para aislar un componente de los componentes que lo rodean, puede agregar sus componentes secundarios. El siguiente diagrama muestra cómo la creación de apéndices de esta manera afectaría una jerarquía de componentes típica.

Amplificar un componente por lo general significa reemplazarlo con un componente “suplente” simple sin estado, lógica y una plantilla mínima.

Por ejemplo, podrías reemplazar esto:

export default {
  name: "MyComponent",
  template: "..."
  props: { ... },
  methods: { ... },
  computed: { ... }
  ...
};

con este:

export default {
  name: "MyComponentStub"
  template: "<div></div>"
};

Sin embargo, en lugar de crear componentes secundarios manualmente, Vue Test Utils ofrece la shallowMount característica que lo hace automáticamente.

Componentes acoplados

En el mundo real, los componentes no siempre están completamente desacoplados. A veces, un componente se basa en un componente secundario y, por lo tanto, el componente secundario no se puede bloquear sin perder alguna funcionalidad.

Por ejemplo, supongamos que creamos un botón con una animación genial y queremos reutilizarlo en una aplicación, por lo que decidimos crear un componente personalizado llamado animated-button.

ahora tenemos el my-form componente que utiliza este componente de botón. Se ha implementado de tal manera que my-form está acoplado a animated-buttonya que este último emite un evento de “clic” que se utiliza para activar el submit método en el primero.

MiForm.vue

<template>
  <input name="email" v-model="email" />
  <animated-button title="Submit" @click="submit" />
  <!--more markup and children components here-->
</template>
<script>
import AnimatedButton from "@/component/AnimatedButton";
...
export default {
  data: () => ({
    email: null
  }),
  methods: {
    submit () {
      this.$store.commit("FORM_SUBMIT", email);
    }
  }
  components: {
    AnimatedButton,
    AnotherChildComponent,
    SomeOtherChildComponent
    ...
  }
}
</script>

Unidad de prueba my-form

Otra idea clave de las pruebas unitarias es que queremos probar las entradas y salidas de la unidad y considerar las partes internas como una caja negra.

En el my-form componente, debemos hacer una prueba unitaria donde la entrada es el clic del botón, mientras que la salida es la confirmación de Vuex.

Llamaremos a esta prueba “debe confirmar FORM_SUBMIT cuando se hace clic en el botón”. Lo crearemos montando MyForm primero superficialmente para aislarlo de la influencia de los componentes secundarios como se indicó anteriormente.

MiForm.spec.js

import { shallowMount } from "@vue/test-utils";
import MyForm from "@/components/MyForm";

describe("MyForm.vue", () => {
  it("should commit FORM_SUBMIT when button clicked", () => {
    const wrapper = shallowMount(MyForm);

  });
});

A continuación, usaremos el envoltorio find Método API para encontrar el componente del botón. Pasamos un selector de CSS "animated-button" como estrategia de localización. Entonces podemos encadenar el trigger método y pase “clic” como argumento. Así es como generamos la entrada de la prueba.

Luego podemos afirmar que se realiza un compromiso de Vuex (probablemente usando un espía, pero eso no es relevante para este artículo, por lo que no lo detallaré).

MiForm.spec.js

it("should commit FORM_SUBMIT when button clicked", () => {
  const wrapper = shallowMount(MyForm);
  wrapper.find("animated-button").trigger("click");
  // assert that $store.commit was called
});

Si intentamos ejecutar eso, obtendremos este error de Vue Test Utils:

find no devolvió el botón animado, no puede llamar a trigger() en Wrapper vacío

¿Está mal el selector de CSS? No, el problema es que montamos el componente a poca profundidad, por lo que todos los niños quedaron aplastados. El proceso de auto-stub cambia el nombre de AnimatedButton a “animated-button-stub” en la plantilla.

Pero cambiar el selector de “botón animado” a “talón de botón animado” no es una solución. Los resguardos automáticos no tienen lógica interna, por lo que el evento de clic que activamos en él no se escucha de todos modos.

Desbloqueo selectivo

Todavía queremos un montaje poco profundo my-form, ya que queremos asegurarnos de que esté aislado de la influencia de sus hijos. Pero animated-button es una excepción ya que su funcionalidad es necesaria para la prueba.

Vue Test Utils nos permite especificar el stub para un componente en particular en lugar de usar un stub automático cuando se realiza un montaje poco profundo. Así que el truco es “unstub” animated-button utilizando su definición de componente original como código auxiliar para que conserve toda su funcionalidad.

Para hacer esto, importemos el componente AnimatedButton en la parte superior del archivo. Ahora, vayamos a nuestra prueba y creemos una const. stubs y asignarle un objeto. podemos poner AnimatedButton como una propiedad de objeto abreviada.

Ahora, pasaremos stubs como parte de nuestra configuración de montaje superficial. También reemplazaremos el selector CSS con la definición del componente, ya que esta es la forma preferida de usar el find método.

MiForm.spec.js

import { shallowMount } from "@vue/test-utils";
import MyForm from "@/components/MyForm";
import AnimatedButton from "@/component/AnimatedButton"

describe("MyForm.vue", () => {
  it("should commit FORM_SUBMIT when button clicked", () => {
    const stubs = {
      AnimatedButton
    };
    const wrapper = shallowMount(MyForm, { stubs });
    wrapper.find(AnimatedButton).trigger("click");
    ...
  });
});

Hacerlo de esta manera debería darle una marca verde.

Envolver

Siempre desea aislar sus componentes en una prueba unitaria, lo que se puede lograr fácilmente al unir todos los componentes secundarios con shallowMount.

Sin embargo, si su componente está estrechamente relacionado con uno de sus elementos secundarios, puede “desconectar” selectivamente ese componente proporcionando la definición del componente como un código auxiliar y anulando el código auxiliar automático.


Conviértase en un desarrollador sénior de Vue en 2020.

Aprenda y domine lo que saben los profesionales sobre la creación, prueba e implementación de aplicaciones Vue de pila completa en nuestro curso más reciente.

Aprende más


Similar Posts

Leave a Reply

Your email address will not be published.