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

Angular Material CDK数据表结合NgRx Store单元测试参数解析错误求助

解决Angular单元测试中ObservableDataSource参数无法解析的问题

错误原因分析

这个错误提示Can't resolve all parameters for ObservableDataSource: ([object Object], ?)说明你的ObservableDataSource构造函数有两个参数,Angular的依赖注入系统能解析第一个参数,但第二个参数找不到对应的提供者。通常是因为测试模块中没有配置好该类所需的全部依赖,或者构造函数的参数类型没有被正确识别(比如使用了非类类型的参数,却没添加@Inject()装饰器)。

具体解决步骤

1. 先明确ObservableDataSource的构造函数依赖

首先确认你的ObservableDataSource构造函数的参数结构,比如它可能是这样的:

import { DataSource } from '@angular/cdk/collections';
import { Store } from '@ngrx/store';
import { SomeService } from './some.service';
import { Observable } from 'rxjs';

export class ObservableDataSource<T> extends DataSource<T> {
  constructor(
    private store: Store<YourAppState>,
    private dataService: SomeService // 第二个待解析的依赖
  ) {
    super();
  }

  connect(): Observable<T[]> {
    // 结合ngrx store的数据选择逻辑
    return this.store.select(selectYourTargetData);
  }

  disconnect() {}
}

2. 在测试模块中配置所有依赖的提供者

在组件的单元测试文件里,你需要在TestBed.configureTestingModule中为ObservableDataSource的所有构造函数参数提供mock实例或对应依赖:

import { ComponentFixture, TestBed } from '@angular/core/testing';
import { YourComponent } from './your.component';
import { ObservableDataSource } from './observable-data-source';
import { Store } from '@ngrx/store';
import { provideMockStore } from '@ngrx/store/testing';
import { SomeService } from './some.service';

describe('YourComponent', () => {
  let component: YourComponent;
  let fixture: ComponentFixture<YourComponent>;
  let mockStore: any;
  let mockSomeService: jasmine.SpyObj<SomeService>;

  beforeEach(async () => {
    // 创建mock服务,模拟原服务的方法
    mockSomeService = jasmine.createSpyObj('SomeService', ['fetchExtraData']);

    await TestBed.configureTestingModule({
      declarations: [YourComponent],
      providers: [
        // 注册ObservableDataSource,让DI系统能创建它的实例
        ObservableDataSource,
        // 为ngrx store提供mock实例,传入初始状态
        provideMockStore({ initialState: { yourFeature: {} } }),
        // 提供mock的SomeService替代真实服务
        { provide: SomeService, useValue: mockSomeService }
      ]
    }).compileComponents();
  });

  beforeEach(() => {
    fixture = TestBed.createComponent(YourComponent);
    component = fixture.componentInstance;
    mockStore = TestBed.inject(Store);
    fixture.detectChanges();
  });

  it('should create the component', () => {
    expect(component).toBeTruthy();
  });
});

3. 特殊情况:处理非类类型的构造参数

如果你的ObservableDataSource构造函数中有非类类型的参数(比如配置对象、字符串常量),需要用@Inject()装饰器标记它,同时在测试中提供对应的注入token:

比如构造函数是这样的:

import { Inject, InjectionToken } from '@angular/core';

// 定义注入token
export const DATA_TABLE_CONFIG = new InjectionToken<{ pageSize: number }>('data.table.config');

export class ObservableDataSource<T> extends DataSource<T> {
  constructor(
    private store: Store<YourAppState>,
    @Inject(DATA_TABLE_CONFIG) private config: { pageSize: number }
  ) {
    super();
  }
}

那测试中需要补充这个token的提供者:

providers: [
  ObservableDataSource,
  provideMockStore({ initialState: {} }),
  { provide: DATA_TABLE_CONFIG, useValue: { pageSize: 20 } }
]

4. 确认组件中正确注入ObservableDataSource

还要确保你的组件是通过依赖注入获取ObservableDataSource,而不是手动new实例:

@Component({
  selector: 'app-your-component',
  templateUrl: './your.component.html'
})
export class YourComponent {
  dataSource: ObservableDataSource<YourDataType>;

  // 通过构造函数注入,而非手动new
  constructor(dataSource: ObservableDataSource<YourDataType>) {
    this.dataSource = dataSource;
  }
}

如果是手动new的,那测试中需要自己传入所有构造参数,而非依赖Angular的DI系统。

总结

核心思路就是确保ObservableDataSource的所有构造函数参数,在测试模块的providers数组中都有对应的提供者——不管是mock服务、ngrx的mock store,还是自定义的注入token,都要配置到位,这样Angular的DI系统才能正确解析所有参数,解决这个错误。

内容的提问来源于stack exchange,提问作者Charlie-Greenman

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 10:26:41