【问题标题】:Jest: TypeError: Cannot read property 'foo' of undefined开玩笑:TypeError:无法读取未定义的属性“foo”
【发布时间】:2020-11-19 21:40:03
【问题描述】:

我正在创建新的 QA 问题来分享我的发现,因为我遇到了与 SO 中已经讨论过的相同的错误,但我的问题在其他地方。参考:Jest: TypeError: Cannot read property of undefined

我收到错误“TypeError:无法读取未定义的属性 'apiUrl'”。我不知道为什么。我已经设置了 esModuleInterop 和 allowSyntheticDefaultImports tsconfig.json 所以我认为所有的导出类型都支持。

服务消费者发生错误

import Axios from 'axios';
import config from '@/services/config.service';

const axios = Axios.create({
  baseURL: config.apiUrl || undefined,
                  ^^^^^^
  ...
});

配置服务导出 const config 甚至作为默认导出的位置

export let config: AppConfig;

...

config = {...}

...

export default config;

我的 tsconfig.json

{
  "compilerOptions": {
    "target": "esnext",
    "module": "esnext",
    "strict": true,
    "jsx": "preserve",
    "importHelpers": true,
    "moduleResolution": "node",
    "experimentalDecorators": true,
    "resolveJsonModule": true,
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "sourceMap": true,
    "baseUrl": ".",
    "types": ["node", "webpack-env", "jest", "googlemaps"],
    "paths": {
      "@/*": ["src/*"],
    },
    "lib": ["esnext", "dom", "dom.iterable", "scripthost"],
    "skipLibCheck": true
  },
  "include": [
    "src/main.ts",
    "src/types/**/*",
    "src/WS_UIkit/src/types/**/*"
  ],
  "exclude": ["node_modules"]
}

我的 jest.config.js

module.exports = {
  preset: '@vue/cli-plugin-unit-jest/presets/typescript-and-babel',
  // testMatch: ['**/*.spec.[jt]s?(x)],'
  testMatch: ['**/*.spec.ts'],
  moduleNameMapper: {
    // FIXES Could not locate module @/types mapped as: .../cart/src/types.
    '^@/types$': '<rootDir>/src/types/index.d',
  },
  transformIgnorePatterns: ['node_modules/(?!(quasar|quasar/*))'],
};

我的 babel 配置

module.exports = {
  presets: ['@vue/app'],
  plugins: [
    [
      'transform-imports',
      {
        quasar: {
          transform: 'quasar/dist/babel-transforms/imports.js',
          preventFullImport: true,
        },
      },
    ],
  ],
};

【问题讨论】:

  • 考虑提供完整的 TS 和 Jest 配置,问题是他们特有的。
  • 是否也有 Babel 配置?请提供。您是否尝试切换到@vue/cli-plugin-unit-jest/presets/typescript
  • @vue/cli-plugin-unit-jest/presets/typescript 的结果相同 :)
  • 此时这是特定于您的 Vue 设置而不是一般的 Jest+TS。我不完全确定为什么它在这一点上起作用。我希望"module": "esnext" 不能单独与@vue/cli-plugin-unit-jest/presets/typescript 一起使用,这将导致未转换的import 和语法错误。确保 tsconfig 真的被 Jest 通过在那里犯语法错误来拾取。如果它仍然有效,那就是问题所在。否则 fork 一个单独的 tsconfig.test.json,将其更改为 "module": "commonjs" 并提供给 Jest。
  • 我不太确定这个 Vue Jest 预设,但我猜配置应该变成 module.exports = require('deepmerge')(require('@vue/cli-plugin-unit-jest/presets/typescript'), { globals: {'ts-jest': { tsConfig: 'tsconfig.test.json' } } }) 之类的东西。如果它有效,还要确保 tsconfig.test.json 也被拾取。

标签: typescript jestjs


【解决方案1】:

我的问题是我已经导出了未初始化的常量导出let config: AppConfig;,然后,稍后将其初始化为config = {...},因此在导出时它是undefined。但对我来说,为什么它可以在应用程序中正常工作而没有错误,这对我来说是个谜,也许它执行代码然后解析导出?开玩笑呢?为什么不一样?使用的不是同一个 ts 编译器吗?至少我的问题解决了。

【讨论】:

  • ESModule 导入是所谓的“实时绑定”,当您导出一个 const(或一个变量)然后修改它时 - 它会在 import 它的所有文件中发生变化 - 这与范围不同在 JS 的其他地方,它启用循环引用。
猜你喜欢
  • 2018-06-17
  • 1970-01-01
  • 2023-03-03
  • 2020-07-10
  • 2017-12-15
  • 2020-06-26
  • 2017-10-18
  • 2022-01-18
  • 2019-08-08
相关资源
最近更新 更多