Почему моя функция Jest mockReturnValue не вызывается? (Используя Vue3 и Vue-Test-Utils-Next)

#vue.js #jestjs #vue-test-utils #vuejs3 #vue-composition-api

#vue.js #jestjs #vue-test-utils #vuejs3 #vue-composition-api

Вопрос:

Я использую API-интерфейс Vue composition и импортирую модуль в однофайловый компонент. Я присваиваю возвращаемое значение модуля переменной в методе setup, а затем возвращаю значение, чтобы шаблон мог использовать переменную. Компонент отображает один ItemComponent для каждого элемента, полученного из импортированного модуля.

Фактическое приложение работает нормально и отображает правильное количество элементов. С другой стороны, мой тест не выполняется, и, похоже, функция mockReturnValue не вызывается.

Однофайловый код компонента

 <template>
  <ul class="ItemList">
    <ItemComponent
      v-for="item in items"
      :key="item.id"
      :item="item" />
  </ul>
</template>

<script lang="ts">
import { defineComponent } from 'vue';
import ItemComponent from '@/components/ItemComponent.vue';

import module from '@/module';

export default defineComponent({
  components: {
   ItemComponent,
  },
  setup() {
    const { items } = module.property // note destructuring here
    console.log(items);
    return { items };
  },
});
</script>
  

mock-module.ts

 export const property = {
  items: jest.fn(),
};
  

(макет) index.ts

 import {module} from './modules/mock-module';

export default {module}
  

Тестовый файл

   import module from '@/modules/__mocks__/index.ts';
  jest.mock('../../../src/modules/index.ts');

  it('should render an ItemComponent for each item', () => {
    module.property.items.mockReturnValue([{}, {}, {}]); // Doesn't seem to get invoked?
    const wrapper = mount(MyComponent, { shallow: true });
    expect(wrapper.findAllComponents('item-component-stub').length)
      .toBe(3);
  });
  

Результат

Тест завершается с ошибкой и находит 0 элементов, и когда я console.log(items) из однофайлового компонента получаю следующее:

  [Function: mockConstructor] {
        _isMockFunction: true,
        getMockImplementation: [Function (anonymous)],
        mock: [Getter/Setter],
        mockClear: [Function (anonymous)],
        mockReset: [Function (anonymous)],
        mockRestore: [Function (anonymous)],
        mockReturnValueOnce: [Function (anonymous)],
        mockResolvedValueOnce: [Function (anonymous)],
        mockRejectedValueOnce: [Function (anonymous)],
        mockReturnValue: [Function (anonymous)],
        mockResolvedValue: [Function (anonymous)],
        mockRejectedValue: [Function (anonymous)],
        mockImplementationOnce: [Function (anonymous)],
        mockImplementation: [Function (anonymous)],
        mockReturnThis: [Function (anonymous)],
        mockName: [Function (anonymous)],
        getMockName: [Function (anonymous)]
      }
  

Это указывает (для меня), что тест использует макет файла, но по какой-то причине не вызывает .mockReturnValue() вызов. Если я просто изменю фиктивную зависимость от jest.fn() на некоторое фактическое значение, консоль.оператор log возвращает это значение. Конечно, я не хочу этого делать, так как мне нужно иметь возможность устанавливать разные возвращаемые значения в разных тестах.

Чего я ожидаю, я ожидал бы, когда я вызываю module.property.items.mockReturnValue([{}, {}, {}]) эту консоль.log напечатал бы массив с тремя пустыми объектами, и тест прошел бы с отображением 3/3 ItemComponents.

Ответ №1:

items: jest.fn() создает items шпиона. Вывод на консоль — это тот, который следует ожидать, он показывает, что это функция. mockReturnValue не имеет шансов не быть вызванным, если тест продолжается. Его результат можно рассматривать как:

 module.property.items.mockReturnValue([{}, {}, {}])
expect(module.property.items()).toEqual([{}, {}, {}])
  

Поскольку items предполагается, что это массив, а не функция, его неправильно подделали. Обычно это делается путем прямого изменения свойств без jest.mock выполнения в этом модуле:

 module.property = [{}, {}, {}]
  

Дополнительно должно быть гарантировано, что измененное значение не повлияет на другие тесты, например, выполнив это, jest.isolateModules чтобы повторно импортировать иерархию затронутых модулей.

Это также можно сделать с помощью Jest spies, но для легкого доступа к ней требуется сохранить ссылку на функцию getter:

 export const property = {
  items: null,
};

export const mockPropertyItems = jest.spyOn(property, 'items', 'get');
  

И используется как:

 module.mockPropertyItems.mockReturnValue([{}, {}, {}])
expect(module.property.items).toEqual([{}, {}, {}])
  

Также импорт напрямую из __mocks__ неверен, издевательский модуль должен быть импортирован из его обычного местоположения.