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

使用Vitest作为测试运行器时NestJS Testing Module依赖注入失败

NestJS Testing Module与Vitest配合时依赖注入失败问题

问题重现

使用NestJS Testing Module配合Vitest执行测试时,服务无法正确注入,调用方法出现Cannot read properties of undefined (reading 'foo')错误。手动实例化服务的测试可正常运行,但通过Testing Module注入的测试报错。

服务代码

RandomService

import { InjectedOneService } from './injected-one.service';
import { InjectedTwoService } from './intjected-two.service';

export class RandomService {
  constructor(
    private readonly injectedOneService: InjectedOneService,
    private readonly injectedTwoService: InjectedTwoService,
  ) { }
  getStr() {
    return `${this.injectedOneService.foo()} ${this.injectedTwoService.bar()}`;
  }
}

InjectedOneService

import { Injectable } from '@nestjs/common';

@Injectable()
export class InjectedOneService {
  foo() {
    return 'foo';
  }
}

InjectedTwoService

import { Injectable } from '@nestjs/common';

@Injectable()
export class InjectedTwoService {
  constructor() { }
  bar() {
    return 'bar';
  }
}

测试代码

import { Test, TestingModule } from '@nestjs/testing';
import { RandomService } from './service';
import { InjectedOneService } from './injected-one.service';
import { InjectedTwoService } from './intjected-two.service';
import { describe, it, expect, vi } from 'vitest';

describe('Service', () => {
  it('should work without testing module', () => {
    const injectedOneMockService = new InjectedOneService();
    const injectedTwoMockService = new InjectedTwoService();
    const result = new RandomService(
      injectedOneMockService,
      injectedTwoMockService,
    );
    injectedOneMockService.foo = vi.fn().mockImplementation(() => 'mock foo');
    expect(result).toBeDefined();
    expect(result.getStr()).toBe('mock foo bar');
  });
  it('should work with testing module', async () => {
    const module: TestingModule = await Test.createTestingModule({
      providers: [RandomService, InjectedOneService, InjectedTwoService],
    }).compile();

    const injectedOneMockService =
      module.get<InjectedOneService>(InjectedOneService);

    const injectedTwoMockService =
      module.get<InjectedTwoService>(InjectedTwoService);

    const result = module.get<RandomService>(RandomService);

    injectedOneMockService.foo = vi.fn().mockImplementation(() => 'mock foo');
    injectedTwoMockService.bar = vi.fn().mockImplementation(() => 'mock bar');

    expect(result).toBeDefined();
    expect(result.getStr()).toBe('mock foo mock bar');
  });
});

报错信息

TypeError: Cannot read properties of undefined (reading 'foo')
 ❯ RandomService.getStr src/vitest-test/service.ts:10:39
      8|   ) { }
      9|   getStr() {
     10|     return `${this.injectedOneService.foo()} ${this.injectedTwoService.bar()}`;
       |                                       ^
     11|   }
     12| }

Vitest配置文件

import swc from 'unplugin-swc';
import { defineConfig } from 'vitest/config';

export default defineConfig({
  test: {
    globals: true,
    root: './',
  },
  plugins: [
    swc.vite({
      module: { type: 'es6' },
    }),
  ],
});

问题原因与解决方法

1. RandomService缺少@Injectable()装饰器

NestJS的依赖注入系统需要通过@Injectable()装饰器标记可注入的服务。你的RandomService未添加该装饰器,导致Testing Module无法识别并处理它的依赖注入逻辑,最终实例化时内部依赖为undefined。

修复代码:

import { Injectable } from '@nestjs/common'; // 导入装饰器
import { InjectedOneService } from './injected-one.service';
import { InjectedTwoService } from './injected-two.service';

@Injectable() // 添加装饰器
export class RandomService {
  constructor(
    private readonly injectedOneService: InjectedOneService,
    private readonly injectedTwoService: InjectedTwoService,
  ) { }
  getStr() {
    return `${this.injectedOneService.foo()} ${this.injectedTwoService.bar()}`;
  }
}

2. 导入路径拼写错误

检查RandomService和测试文件中对InjectedTwoService的导入路径:./intjected-two.service存在拼写错误(少了字母j),正确路径应为./injected-two.service。路径错误会导致实际注入的依赖为undefined,也是报错的潜在原因。

修复导入路径:

// RandomService中
import { InjectedTwoService } from './injected-two.service';

// 测试文件中
import { InjectedTwoService } from './injected-two.service';

验证修复

完成上述修改后重新运行测试,Testing Module即可正确注入依赖,测试应当正常通过。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 05:17:46