You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

添加JEST自定义报告器引发编译错误:Class extends value undefined

问题分析与解决方案

你遇到的错误 Class extends value undefined is not a constructor or null 本质是在加载 country.model.ts 时,某个被继承的类(比如 ORM 的基类)未被正确解析,导致其值为 undefined。结合你的配置和场景,以下是针对性的解决方案:


1. 使用动态导入避免加载顺序问题

问题大概率出在模块加载顺序上:Jest 加载自定义报告器时,项目内的模块(如 Resolver、Model)可能还未完成初始化,或者存在循环依赖导致类未被正确解析。

修改 test-reporter.ts,将顶层导入改为 onRunComplete 内的动态导入:

import { Reporter, TestContext } from '@jest/reporters';
import { AggregatedResult } from '@jest/test-result';
import { Config } from '@jest/types';
import config from '../config/config';
import { buildSchema } from 'type-graphql';

type CustomReporter = Pick<Reporter, 'onRunComplete'>;

interface Options {
    useReporter: boolean;
}

export default class TestReporter implements CustomReporter {
    constructor(private config: Config.InitialOptions, private options: Options) {}

    async onRunComplete(context: Set<TestContext>, results: AggregatedResult) {
        console.log('Your report is available!');

        // 动态导入 Resolver,避免初始化阶段的加载问题
        const { FundMutationResolver, FundQueryResolver } = await import('@src/investorPortal/funds/resolvers/app/fund.resolver');
        
        const schema = await buildSchema({
            resolvers: [FundMutationResolver, FundQueryResolver],
            authChecker: () => true,
        });
    }
}

2. 验证 tsconfig-paths 配置正确性

确保报告器的路径解析与项目一致,可在 test-reporter/index.js 中添加日志排查:

require('reflect-metadata');
const tsNode = require('ts-node');
const tsConfigPaths = require("tsconfig-paths");
const path = require('path');

const tsconfigPath = path.join(__dirname, '../../tsconfig.json');
const tsconfig = require(tsconfigPath);

// 打印关键路径,确认是否正确指向项目根目录
console.log('tsconfigPath:', tsconfigPath);
console.log('baseUrl:', path.dirname(tsconfigPath));

tsNode.register({
    compilerOptions: tsconfig.compilerOptions,
    transpileOnly: true,
});

tsConfigPaths.register({
    baseUrl: path.dirname(tsconfigPath),
    paths: tsconfig.compilerOptions.paths
});

// 测试路径解析是否正常
const resolverPath = require.resolve('@src/investorPortal/funds/resolvers/app/fund.resolver');
console.log('Resolved resolver path:', resolverPath);

module.exports = require('./test-reporter');

如果路径解析错误,调整 tsconfigPath 的相对路径,确保指向项目根目录的 tsconfig.json。


3. 预编译报告器为 JavaScript

避免在 Jest 运行时使用 ts-node 编译报告器,直接预编译为 CommonJS 模块:

  1. 在项目根目录添加编译脚本(如 scripts/compile-reporter.js):
const { execSync } = require('child_process');
execSync('tsc --project ./e2e/test-reporter/tsconfig.json', { stdio: 'inherit' });
  1. 为报告器单独创建 tsconfig.json(e2e/test-reporter/tsconfig.json):
{
  "extends": "../../tsconfig.json",
  "compilerOptions": {
    "outDir": "./dist",
    "rootDir": "./"
  },
  "include": ["*.ts"]
}
  1. 修改 jest.config.js 指向编译后的报告器:
reporters: ['default', '<rootDir>/e2e/test-reporter/dist/test-reporter.js'],
  1. 运行测试前先执行编译脚本。

4. 排查循环依赖

使用工具(如 madge)检查项目内的循环依赖:

npm install -g madge
madge --circular src/

如果发现 country.model.ts 与其他模块存在循环依赖,重构代码打破循环(比如提取公共接口、使用依赖注入)。


内容的提问来源于stack exchange,提问作者Karim Chaari

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 09:45:35