Метод в базовом классе не существует во время модульного тестирования с mocha компонента Vue

#typescript #unit-testing #inheritance #vue.js #mocha.js

#typescript #модульное тестирование #наследование #vue.js #mocha.js

Вопрос:

Когда у меня есть компонент в Vue, который расширяется из базового класса, он работает во время выполнения в браузере, как и ожидалось. Но при модульном тестировании с mocha метод в базовом классе исчезает. В простом примере ниже это приводит к ошибке TypeError: this.methodInBaseClass is not a function . Но во время выполнения он работает, тогда отображается сообщение Some other data , как я и ожидал.

Что происходит не так? И что более важно, как это исправить?

Рассмотрим этот простой компонент Vue:

 <template>
    <div>{{ myData }}</div>
</template>

<script lang="ts">
import { Component, Prop, Vue } from 'vue-property-decorator';
import BaseClass from '@/components/BaseClass.vue';

@Component
export default class HelloWorld extends BaseClass {
    @Prop() private msg!: string;

    private created(): void {
        this.methodInBaseClass();
    }
}
</script>
  

и базовый класс

 <script lang="ts">
import { Component, Prop, Vue } from 'vue-property-decorator';
export default class BaseClass extends Vue {
    protected myData: string = 'Some data';

    protected methodInBaseClass(): void {
        this.myData = 'Some other data';
    }
}
</script>
  

и модульный тест

 import { expect } from 'chai';
import { shallowMount } from '@vue/test-utils';
import HelloWorld from '@/components/HelloWorld.vue';

describe('HelloWorld.vue', () => {
    it('Data is mutated', () => {
        const wrapper = shallowMount(HelloWorld);
        expect(wrapper.html()).to.include('Some other data');
    });
});
  

Ответ №1:

Вам нужно добавить Component декоратор в базовый класс, чтобы метод methodInBaseClass можно было объявить как методы vue-объекта:

 <script lang="ts">
import { Component, Prop, Vue } from 'vue-property-decorator';
@Component
export default class BaseClass extends Vue {
    protected myData: string = 'Some data';

    protected methodInBaseClass(): void {
        this.myData = 'Some other data';
    }
}
</script>
  

Комментарии:

1. Да, это работает. Отлично. Спасибо. Но когда я делаю базовый класс абстрактным, я больше не могу помещать @Component в класс. Но вместо абстрактных классов у меня будут методы с throw new Error('Not implemented'); или около того в качестве обходного пути. Тем не менее, я не понимаю, почему он работает во время выполнения, но не в модульном тестировании.

Ответ №2:

Если вы хотите использовать Component декоратор в абстрактном классе, вы можете использовать следующий взлом.

Создайте новый AbstractComponent декоратор:

 import { Component } from 'vue-property-decorator';
export default function AbstractComponent(v: any) {
    return Component(v);
}
  

Вы сможете использовать AbstractComponent декоратор в абстрактном классе и получить ту же функциональность, что и Component декоратор.