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

Angular4中Jasmine测试NgRx沙箱类时注入失败问题

解决Angular4测试NgRx沙箱类时的注入失败问题

看起来你的测试模块没有正确配置MonitoringSandbox的依赖注入,导致Angular的测试注入器找不到这个类的提供者,最终抛出StaticInjectorError并让沙箱对象返回undefined。下面一步步帮你解决这个问题:

1. 补全测试模块的依赖配置

你的TestBed.configureTestingModule只导入了UnitTestsModule,但如果这个模块没有导出或提供MonitoringSandbox,Angular就无法找到它。你需要显式在providers数组中添加沙箱类,同时mock它的两个依赖服务(测试沙箱不需要真实的服务实现,用模拟对象即可):

beforeEach(async(() => {
  TestBed.configureTestingModule({
    imports: [UnitTestsModule],
    providers: [
      // 提供沙箱类本身
      MonitoringSandbox,
      // Mock DeviceService(这里可以留空,因为测试用例暂时没用到它的方法)
      { provide: DeviceService, useValue: jasmine.createSpyObj('DeviceService', ['']) },
      // Mock AppStateManagerService,需要包含沙箱用到的getFromStore和saveToStore方法
      { 
        provide: AppStateManagerService, 
        useValue: jasmine.createSpyObj('AppStateManagerService', ['getFromStore', 'saveToStore']) 
      }
    ]
  }).compileComponents(); // Angular4中如果涉及组件模板,需要加上这个编译步骤
}));

2. 正确获取沙箱实例

你原来用inject在第二个beforeEach中赋值this.MonitoringSandbox,这种方式容易出现上下文问题。更可靠的做法是直接用TestBed.get()获取实例:

// 提前声明变量
let monitoringSandbox: MonitoringSandbox;
let appStateManager: jasmine.SpyObj<AppStateManagerService>;

beforeEach(() => {
  monitoringSandbox = TestBed.get(MonitoringSandbox);
  appStateManager = TestBed.get(AppStateManagerService);
});

3. 修正测试用例中的方法名(注意点)

另外,你测试用例里调用的setSelectedRow和getSelectedRow,在你提供的MonitoringSandbox代码里并不存在——对应的实际方法是setSelectedDevice和getDeviceIdWithRowIndex。如果这是笔误,记得修正测试用例的方法调用,否则即使注入成功,测试也会失败。

完整修正后的测试代码示例

describe('MonitoringSandbox', () => {
  let monitoringSandbox: MonitoringSandbox;
  let appStateManager: jasmine.SpyObj<AppStateManagerService>;

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      imports: [UnitTestsModule],
      providers: [
        MonitoringSandbox,
        { provide: DeviceService, useValue: jasmine.createSpyObj('DeviceService', ['']) },
        { 
          provide: AppStateManagerService, 
          useValue: jasmine.createSpyObj('AppStateManagerService', ['getFromStore', 'saveToStore']) 
        }
      ]
    }).compileComponents();
  }));

  beforeEach(() => {
    monitoringSandbox = TestBed.get(MonitoringSandbox);
    appStateManager = TestBed.get(AppStateManagerService);
  });

  it('should set selected device correctly', () => {
    const testDeviceId = '143';
    monitoringSandbox.setSelectedDevice(testDeviceId);
    
    // 验证AppStateManager的saveToStore方法是否被正确调用
    expect(appStateManager.saveToStore).toHaveBeenCalledWith(new SetSelectedDevice(testDeviceId));
  });

  it('should get device id list from store', () => {
    const mockKvRows: Array<RowIdDeviceIdKeyValue> = [{ rowId: '1', deviceId: 'dev1' }];
    // 模拟getFromStore返回的Observable
    appStateManager.getFromStore.and.returnValue(of(mockKvRows));
    
    monitoringSandbox.getDeviceIdWithRowIndex().subscribe(kvRows => {
      expect(kvRows).toEqual(mockKvRows);
    });
  });
});

为什么原来的代码会失败?

本质原因是测试模块没有提供MonitoringSandbox及其依赖服务,Angular无法创建这个类的实例,所以注入时抛出StaticInjectorError,最终导致this.MonitoringSandbox为undefined。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 09:34:19