Search code examples
vue.jsvuejs2jestjsvue-test-utils

mount() and shallowMount() from @vue/test-utils throw TypeError: Cannot read property 'components' of undefined


I am trying to set up unittesting for my Vue app but everytime I run my test the mount or shallowMount function throws me a TypeError: Cannot read property 'components' of undefined error. I tried the @vue/test-utils versions 1.0.0-beta.32, 1.0.0-beta.31 and 1.0.0-beta.27 but to no avail.

The error message:

 ActuatorController
    ✕ is a Vue instance (24ms)

  ● ActuatorController › is a Vue instance

    TypeError: Cannot read property 'components' of undefined

       5 | 
       6 | beforeEach(() => {
    >  7 |   wrapper = mount(ActuatorController);
         |             ^
       8 | });
       9 | 
      10 | afterEach(() => {

      at createInstance (node_modules/@vue/test-utils/dist/vue-test-utils.js:2537:22)
      at mount (node_modules/@vue/test-utils/dist/vue-test-utils.js:13525:18)
      at Object.<anonymous> (apps/actuator_controller/static/actuator_controller/__tests__/ActuatorController.test.js:7:13)

  ● ActuatorController › is a Vue instance

    TypeError: Cannot read property 'isVueInstance' of undefined

      14 | describe("ActuatorController", () => {
      15 |   test("is a Vue instance", () => {
    > 16 |     expect(wrapper.isVueInstance()).toBeTruthy();
         |                    ^
      17 |   });
      18 | });
      19 | 

      at Object.<anonymous> (apps/actuator_controller/static/actuator_controller/__tests__/ActuatorController.test.js:16:20)

  ● ActuatorController › is a Vue instance

    TypeError: Cannot read property 'destroy' of undefined

       9 | 
      10 | afterEach(() => {
    > 11 |   wrapper.destroy();
         |           ^
      12 | });
      13 | 
      14 | describe("ActuatorController", () => {

      at Object.<anonymous> (apps/actuator_controller/static/actuator_controller/__tests__/ActuatorController.test.js:11:11)

Test Suites: 1 failed, 1 total
Tests:       1 failed, 1 total
Snapshots:   0 total
Time:        20.601s

Here is my package.json

  "name": "igp-package",
  "version": "1.0.0",
  "scripts": {
    "build": "webpack",
    "test": "jest"
  },
  "dependencies": {
    "lodash": "^4.17.15",
    "mxgraph": "^4.1.0",
    "vue": "^2.6.11",
    "vuetify": "^2.2.15"
  },
  "devDependencies": {
    "@babel/core": "^7.8.7",
    "@vue/babel-preset-app": "^4.2.3",
    "@vue/test-utils": "^1.0.0-beta.32",
    "babel-core": "^7.0.0-bridge.0",
    "babel-eslint": "^10.1.0",
    "babel-jest": "^25.2.4",
    "babel-loader": "^8.0.6",
    "css-loader": "^3.2.0",
    "deepmerge": "^4.2.2",
    "eslint": "^6.8.0",
    "eslint-config-prettier": "^6.10.1",
    "eslint-loader": "^3.0.3",
    "eslint-plugin-jest": "^23.8.2",
    "eslint-plugin-prettier": "^3.1.2",
    "eslint-plugin-vue": "^6.2.2",
    "fibers": "^4.0.2",
    "file-loader": "^4.3.0",
    "flush-promises": "^1.0.2",
    "jest": "^25.2.4",
    "jest-transform-stub": "^2.0.0",
    "jest-serializer-vue": "^2.0.2",
    "json-loader": "^0.5.7",
    "prettier": "^2.0.2",
    "sass": "^1.26.2",
    "sass-loader": "^8.0.2",
    "style-loader": "^1.0.0",
    "vue-cli-plugin-webpack-bundle-analyzer": "~2.0.0",
    "vue-jest": "^3.0.5",
    "vue-loader": "^15.9.0",
    "vue-style-loader": "^4.1.2",
    "vue-template-compiler": "^2.6.11",
    "vuetify-loader": "^1.4.3",
    "webpack": "^4.41.2",
    "webpack-bundle-analyzer": "^3.6.1",
    "webpack-cli": "^3.3.10"
  }
}

My jest.config.js

module.exports = {
  verbose: true,
  moduleFileExtensions: ["js", "jsx", "json", "vue"],
  transform: {
    "^.+\\.vue$": "vue-jest",
    "^.+\\.(js|jsx)?$": "babel-jest",
  },
  snapshotSerializers: ["jest-serializer-vue"],
  testMatch: ["**/__tests__/*.test.(js|jsx|ts|tsx)"],
  collectCoverage: false,
  collectCoverageFrom: ["**/*.{js,vue}", "!**/node_modules/**"],
};

Here the test file:

import { mount } from "@vue/test-utils";
import { ActuatorController } from "../Vue/ActuatorController.vue";

let wrapper;

beforeEach(() => {
  wrapper = mount(ActuatorController);
});

afterEach(() => {
  wrapper.destroy();
});

describe("ActuatorController", () => {
  test("is a Vue instance", () => {
    expect(wrapper.isVueInstance()).toBeTruthy();
  });
});

And at last the component used for the test:

<template>
  <div>
    <h1>Title</h1>
  </div>
</template>

<script>
export default {
  name: "ActuatorController",
};
</script>

<style scoped></style>

I hope this is all the necessary information. Thanks in advance for your efforts to help me :)

Cheers, Niko


Solution

  • The error means that mount tries to read components property of ActuatorController and fails.

    Components are default exports in Vue single file components, while ActuatorController is named import and is undefined.

    It should be:

    import ActuatorController from "../Vue/ActuatorController.vue";