it-source

vue 컴포넌트의 $route 개체를 모킹하는 쓰기 테스트 방법

criticalcode 2022. 10. 21. 22:51
반응형

vue 컴포넌트의 $route 개체를 모킹하는 쓰기 테스트 방법

다음과 같은 스테이트먼트를 포함하는 컴포넌트가 있습니다.this.$route.fullPath, 의 가치를 어떻게 조롱해야 하는가?fullPath$route그 컴포넌트를 테스트하려면 어떻게 해야 합니까?

나는 상위 대답에 동의하지 않는다 - 조롱해도 좋다$route문제없이.

반면 기본 생성자에 vue-router를 여러 번 설치하면 문제가 발생합니다.가세하다$route그리고.$router읽기 전용 속성으로 지정합니다.그래서 향후 테스트에서 덮어쓰기가 불가능하죠

vue-test-utils를 사용하여 이를 실현하는 방법은 두 가지가 있습니다.

mocks 옵션을 사용한 vue-router 조롱

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

wrapper.vm.$route.fullPath // 'full/path'

createLocalVue를 사용하여 Vue 라우터를 안전하게 설치할 수도 있습니다.

createLocalVue를 사용한 테스트에서 vue-router를 안전하게 설치

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')

조롱하지 않는 것이 좋다vue-router컴포넌트를 렌더링하기 위해 사용하는 것이 아니라 올바르게 동작하는 라우터를 얻을 수 있습니다.예:

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()
    })
  })
})

주의사항:

  1. vue의 런타임 전용 버전을 사용하고 있기 때문에render: h => h('router-view').
  2. 테스트만 하고 있습니다.totest컴포넌트. 단, 다른 컴포넌트가 참조되고 있는 경우에는 필요한 컴포넌트도 있습니다.totest예:another_component를 참조해 주세요.
  3. 당신은 필요하다nextTickHTML을 보거나 테스트하기 전에 렌더링해야 합니다.

문제들 중 하나는 제가 찾은 대부분의 예들이 이전 버전의vue-router이행 매뉴얼을 참조해 주십시오.예를 들어,router.go()이젠 안 먹혀요

아무도 날 도와주지 않아 그래서 난 그걸 파고들었어vue-test-utils매뉴얼에 기재되어 있는 것으로 판명되었습니다.그래서 Import를 하셔야 합니다.

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

샘플을 작성했습니다.vue사례.테스트 중에는shallowMount그 때문에,vue응용 프로그램인스턴스 및 라우터

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

라우터를 쉽게 통과시켜 얕은 마운트에 연결할 수 있으며, 이 경우 오류가 발생하지 않습니다.사용하는 상점을 통과하려면:

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

그런 다음 가게를 통과합니다.

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

이 솔루션은 다음 오류를 해결했습니다.

  • 사용할 때 정의되지 않은 속성 '파라임'을 읽을 수 없습니다.this.$route.params.id
  • 알 수 없는 사용자 지정 요소router-link

찾은 가장 쉬운 방법은 localVue를 사용하는 것입니다.

import { createLocalVue, mount } from '@vue/test-utils';
import VueRouter from 'vue-router';
import Vuex from 'vuex';

import ComponentName from '@/components/ComponentName.vue';
// Add store file if any getters is accessed
import store from '@/store/store';

describe('File name', () => {
  const localVue = createLocalVue();
  localVue.use(VueRouter);

  // Can also be replaced with route(router.js) file
  const routes = [
    {
      path: '/path',
      component: ComponentName,
      name: 'Route name'
    }
  ];

  const router = new VueRouter({ routes });

  // if needed
  router.push({
    name: 'Route name',
    params: {}
  });

  const wrapper = mount(ComponentName, {
    localVue,
    router,
    store
  });

  test('Method()', () => {
    wrapper.vm.methodName();

    expect(wrapper.vm.$route.path)
      .toEqual(routes[0].path);
  });
});

도움이 되었으면 좋겠어!!!

라우터를 「mock」할 필요는 없습니다.애플리케이션은 VueRouter를 글로벌 vue 범위에서 설정할 수 있지만 테스트에서 원하는 작업을 문제 없이 수행할 수 있습니다.

localVue 사용 현황 읽기VueRouter: https://vue-test-utils.vuejs.org/guides/ #using-with-vue-displays.

나는 현재 우리의 메인 앱에서 복잡한 라우터를 끌어오고 있으며, 그것을 할 수 있다.jest.spyOn()의 콜router.push()에 경로를 할 수도 있습니다.shallowMount()created()

회피책

// 일부 Vue Component.표시하다

<template>
... something
</template>
<script>
...
data () {
  return {
    authenticated: false
  }
},
...
created () {
  if(!this.authenticated && this.$route.path !== '/'){
    this.$router.push('/')
  }
}
</script>

// 일부 Vue Component.spec.js

import Vuex from 'vuex'
import VueRouter from 'vue-router'
import { shallowMount, createLocalVue } from '@vue/test-utils'
import SomeVueComponent from 'MyApp/components/someVueComponent'
import MyAppRouter from 'MyApp/router'
import MyAppCreateStore from 'MyApp/createStore'
import merge from 'lodash.merge'

function setVueUseValues (localVue) {
  localVue.use(Vuex)
  localVue.use(VueRouter)
  // other things here like custom directives, etc
}

beforeEach(() => {
  // reset your localVue reference before each test if you need something reset like a custom directive, etc
  localVue = createLocalVue()
  setVueUseValues(localVue)
})

let localVue = createLocalVue()
setVueUseValues(localVue)

test('my app does not react to path because its default is "/"', () => {
  const options = {
    localVue,
    router: MyAppRouter,
    store: MyAppCreateStore()  
  }  

  const routerPushSpy = jest.spyOn(options.router, 'push')
  const wrapper = shallowMount(SomeVueComponent, options)
  expect(routerPushSpy).toHaveBeenCalledTimes(0)
})

test('my app reacts to path because its not "/" and were not authenticated', () => {
  const options = {
    localVue,
    router: MyAppRouter,
    store: MyAppCreateStore()  
  }

  const routerPushSpy = jest.spyOn(options.router, 'push')
  options.router.push('/nothomepath')
  expect(routerPushSpy).toHaveBeenCalledWith('/nothomepath') // <- SomeVueComponent created hook will have $route === '/nothomepath' as well as fullPath

  const wrapper = shallowMount(SomeVueComponent, options)
  expect(routerPushSpy).toHaveBeenCalledWith('/') // <- works
})

은 제가 '하다'는 한 입니다.$route" " " 전에 되었습니다.SomeVueComponent.vue작성/마운트 됩니다.할 수 있고 컴포넌트 를 할 수 합니다.this.$router.push('/something') 할 수 wrapper.vm 삭제

let routerPushSpy = jest.spyOn(wrapper.vm.$router, 'push') // or before hooks, etc

에서 볼 때 이 있는 것 .vm.$route되어 있지 않기 에 위의 는 다른 방법이입니다.다른 방법은 없습니다.$route는 VueRouter에 전용 때문입니다.$route

vue-test-syslogs 문서 https://vue-test-utils.vuejs.org/guides/ #syslogs-route-and-syslogs에서 다음 절차를 수행합니다.

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

const $route = {
  path: '/some/path'
}

const wrapper = shallowMount(Component, {
  mocks: {
    $route
  }
})

wrapper.vm.$route.path // /some/path

이 문제의 재현에 관심이 있는 경우는, https://github.com/vuejs/vue-test-utils/issues/1136 를 참조해 주세요.

@SCOLvin의 답변에 대해 모두 칭찬합니다.이 시나리오에서는 라우터 링크가 있는 컴포넌트를 사용하여

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

Vue는 라우터와 함께 제공되지 않았기 때문에 유닛 테스트 중@SCOLvin answer를 사용하여 vue-cli가 원래 제공한 테스트를 다시 작성합니다.

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');
  });

로.

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');
  });
});

파라미터를 뷰에 전달할 필요가 없기 때문에 컴포넌트를 디폴트 렌더로서 심플하게 할 수 있어 푸시할 필요도 nextTick을 기다릴 필요도 없습니다.다른 사람이요!

왜 모든 답이 이렇게 복잡하지?다음 작업을 수행할 수 있습니다.

...
wrapper = mount(HappyComponent, {
  mocks: {
    $route: {fullPath: ''}
  },
})
...

@SCOLvin의 훌륭한 답변에 덧붙여, 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
  })
})

이것은 vue-test-utils에도 유효하다고 생각합니다.

vue-test-utils를 사용한 이 예에서는 라우터와 스토어를 모두 조롱하고 있습니다.

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>`
    )
  })
})

기사에 의하면, 다음과 같이 하고 있습니다.

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');
});

VM을 조롱할 수 있습니다.VM을 설정하여 $140._routerRoot._개요

예를들면

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!

https://github.com/vuejs/vue-router/blob/dev/dist/vue-router.js#L558 에서 소스코드를 재확인할 수 있습니다.

내가 찾은 가장 쉬운 방법은 $route를 조롱하는 거야.

it('renders $router.name', () => {
  const $route = {
    name: 'test name - avoriaz'
  }


 const wrapper = shallow(Component, {
    mocks: {
      $route
    }
  })
  expect(wrapper.text()).to.equal($route.name)
})

언급URL : https://stackoverflow.com/questions/41458736/how-to-write-test-that-mocks-the-route-object-in-vue-components

반응형