vue utils util test unit-testing sinon vue-component vuejs2 vue-loader

unit-testing - vue test utils



Cómo escribir una prueba que simula el objeto $ route en componentes vue (10)

Tengo un componente que contiene una declaración como this.$route.fullPath , ¿cómo debo fullPath valor de fullPath del objeto $route si quiero probar ese componente?


Agregando a la gran respuesta de @SColvin, aquí hay un ejemplo de este trabajo usando Avoriaz :

import { mount } from ''avoriaz'' import Vue from ''vue'' import VueRouter from ''vue-router'' import router from ''@/router'' import HappyComponent from ''@/components/HappyComponent'' Vue.use(VueRouter) describe(''HappyComponent.vue'', () => { it(''renders router links'', () => { wrapper = mount(HappyComponent, {router}) // Write your test }) })

Creo que esto debería funcionar también con vue-test-utils .


Eche un vistazo a este ejemplo utilizando vue-test-utils, donde me burlo tanto del enrutador como de la tienda.

import ArticleDetails from ''@/components/ArticleDetails'' import { mount } from ''vue-test-utils'' import router from ''@/router'' describe(''ArticleDetails.vue'', () => { it(''should display post details'', () => { const POST_MESSAGE = ''Header of our content!'' const EXAMPLE_POST = { title: ''Title'', date: ''6 May 2016'', content: `# ${POST_MESSAGE}` } const wrapper = mount(ArticleDetails, { router, mocks: { $store: { getters: { getPostById () { return EXAMPLE_POST } } } } }) expect(wrapper.vm.$el.querySelector(''h1.post-title'').textContent.trim()).to.equal(EXAMPLE_POST.title) expect(wrapper.vm.$el.querySelector(''time'').textContent.trim()).to.equal(EXAMPLE_POST.date) expect(wrapper.vm.$el.querySelector(''.post-content'').innerHTML.trim()).to.equal( `<h1>${POST_MESSAGE}</h1>` ) }) })


El método más fácil que encontré es usar localVue

import { createLocalVue, mount } from ''@vue/test-utils'' import ComponentName from ''componentPath'' import Vuex from ''vuex'' import store from ''@/store/store'' //Add store file if any getters is accessed import VueRouter from ''vue-router'' describe(''File name'', () => { const localVue = createLocalVue() localVue.use(VueRouter) const routes = [ //Can also be rreplaced with route(router.js) file { path: ''/path'', component: ComponentName, name: ''Route name'' } ] const router = new VueRouter({ routes }) router.push({ name: ''Route name'', params: {} }) //if needed const wrapper = mount(ComponentName, {localVue, router, store }) beforeEach(function() { }); it(''Method()'', () => { wrapper.vm.methodName() expect(wrapper.vm.$route.path).toBe(routes[0].path) }); });

¡¡¡Espero eso ayude!!!


Esto es lo que he estado haciendo según este artículo :

it(''renders $router.name'', () => { const scopedVue = Vue.extend(); const mockRoute = { name: ''abc'' }; scopedVue.prototype.$route = mockRoute; const Constructor = scopedVue.extend(Component); const vm = new Constructor().$mount(); expect(vm.$el.textContent).to.equal(''abc''); });


La forma más fácil que he encontrado es burlarse de la ruta $.

it(''renders $router.name'', () => { const $route = { name: ''test name - avoriaz'' } const wrapper = shallow(Component, { mocks: { $route } }) expect(wrapper.text()).to.equal($route.name) })


Lo mejor es no vue-router sino usarlo para renderizar el componente, de esa forma obtendrá un enrutador que funcione correctamente. Ejemplo:

import Vue from ''vue'' import VueRouter from ''vue-router'' import totest from ''src/components/totest'' describe(''totest.vue'', () => { it(''should totest renders stuff'', done => { Vue.use(VueRouter) const router = new VueRouter({routes: [ {path: ''/totest/:id'', name: ''totest'', component: totest}, {path: ''/wherever'', name: ''another_component'', component: {render: h => ''-''}}, ]}) const vm = new Vue({ el: document.createElement(''div''), router: router, render: h => h(''router-view'') }) router.push({name: ''totest'', params: {id: 123}}) Vue.nextTick(() => { console.log(''html:'', vm.$el) expect(vm.$el.querySelector(''h2'').textContent).to.equal(''Fred Bloggs'') done() }) }) })

Cosas a tener en cuenta:

  1. Estoy usando la versión solo en tiempo de ejecución de vue, por render: h => h(''router-view'') tanto render: h => h(''router-view'') .
  2. Solo estoy probando el componente totest , pero es posible que se requieran otros si están referenciados por totest por ejemplo. another_component en este ejemplo.
  3. Necesita nextTick para que el HTML se haya procesado antes de poder verlo / probarlo.

Uno de los problemas es que la mayoría de los ejemplos que encontré se refieren a la versión anterior de vue-router , consulte la documentación de migraciones , por ejemplo. algunos ejemplos usan router.go() que ahora no funciona.


Ninguna respuesta me ayudó, así que profundizo en la documentación de vue-test-utils y encontré una respuesta funcional, por lo que necesitas importar.

import { shallowMount,createLocalVue } from ''@vue/test-utils''; import router from ''@/router.ts''; const localVue = createLocalVue();

Creamos una instancia de vue muestra. Mientras realiza las pruebas, debe usar shallowMount para poder proporcionar una instancia de aplicación vue y un enrutador.

describe(''Components'', () => { it(''renders a comment form'', () => { const COMMENTFORM = shallowMount(CommentForm,{ localVue, router }); }) })

Usted puede pasar fácilmente al enrutador y al montaje superficial, y no le da el error. Si quieres pasar la tienda utilizas:

import { shallowMount,createLocalVue } from ''@vue/test-utils''; import router from ''@/router.ts''; import store from ''@/store.ts''; const localVue = createLocalVue();

Y luego pasar la tienda:

describe(''Components'', () => { it(''renders a comment form'', () => { const COMMENTFORM = shallowMount(CommentForm,{ localVue, router, store }); }) })

Esta solución resolvió los siguientes errores:

  • No se puede leer la propiedad ''params'' de undefined al usar this.$route.params.id
  • Elemento personalizado desconocido router-link


No estoy de acuerdo con la respuesta principal: puedes burlarte de $route sin ningún problema.

Por otro lado, la instalación de vue-router varias veces en el constructor base le causará problemas. Agrega $route y $router como propiedades de solo lectura. Lo que hace que sea imposible sobrescribirlos en futuras pruebas.

Hay dos maneras de lograr esto con vue-test-utils .

Burlándose de vue-router con la opción de mocks

const $route = { fullPath: ''full/path'' } const wrapper = mount(ComponentWithRouter, { mocks: { $route } }) wrapper.vm.$route.fullPath // ''full/path''

También puede instalar Vue Router de forma segura utilizando createLocalVue:

Instalar vue-router de forma segura en las pruebas con createLocalVue

const localVue = createLocalVue() localVue.use(VueRouter) const routes = [ { path: ''/'', component: Component } ] const router = new VueRouter({ routes }) const wrapper = mount(ComponentWithRouter, { localVue, router }) expect(wrapper.vm.$route).to.be.an(''object'')


Puede simularse con vm. $ Router configurando vm._routerRoot._router

Por ejemplo

var Constructor = Vue.extend(Your_Component) var vm = new Constructor().$mount() var your_mock_router = {hello:''there''} vm.$router = your_mock_router //An error ''setting a property that has only a getter'' vm._routerRoot._router = your_mock_router //Wow, it works!

Puede verificar su código fuente aquí: https://github.com/vuejs/vue-router/blob/dev/dist/vue-router.js#L558


Todas las felicitaciones a @SColvin por su respuesta; Ayudé a encontrar una respuesta en mi escenario donde tenía un componente con un enrutador-enlace que estaba lanzando un

ERROR: ''[Vue warn]: Error in render function: (found in <RouterLink>)''

durante la prueba de unidad porque a Vue no se le había suministrado un enrutador. Usando la respuesta de @SColvin para volver a escribir la prueba originalmente suministrada por vue-cli desde

describe(''Hello.vue'', () => { it(''should render correct contents'', () => { const Constructor = Vue.extend(Hello); const vm = new Constructor().$mount(); expect(vm.$el.querySelector(''.hello h1'').textContent) .to.equal(''Welcome to Your Vue.js App''); });

a

describe(''Hello.vue'', () => { it(''should render correct contents'', () => { Vue.use(VueRouter); const router = new VueRouter({ routes: [ { path: ''/'', name: ''Hello'', component: Hello }, ], }); const vm = new Vue({ el: document.createElement(''div''), /* eslint-disable object-shorthand */ router: router, render: h => h(''router-view''), }); expect(vm.$el.querySelector(''.hello h1'').textContent) .to.equal(''Welcome to Your Vue.js App''); }); });

Sin necesidad de pasar parámetros a la vista, podría simplificar el componente como el procesamiento predeterminado, sin necesidad de empujar y sin necesidad de esperar el siguiente clic. HTH alguien más!