【问题标题】:Create Class Instance with Mock Services in Angular Testing在 Angular 测试中使用模拟服务创建类实例
【发布时间】:2020-06-26 19:48:34
【问题描述】:

我在一个 Angular 9 项目中工作。我创建了一个类,它是另一个组件中材质树的数据源。我真的只为组件编写测试,而不是类。 我在测试文件中创建此类的实例时遇到问题。我已经制作了模拟服务并将它们添加到测试文件中的 testBed,如下所示:

class MockMyService {
  getData() {...}
}

describe("DynamicDataSource", () => {
  let dynamicDataSource: DynamicDataSource;
  let mockMyService: MockMyService;

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      providers: [
        { provide: MyService, useClass: MockMyService }
      ]
    }).compileComponents();
  }));

  beforeEach(() => {
    mockMyService = TestBed.inject(MyService);
    dynamicDataSource = new DynamicDataSource(null, null);
  });

  it("should create", () => {
    expect(dynamicDataSource).toBeTruthy();
  });
});

在上面我用dynamicDataSource = new DynamicDataSource(null, null);创建了一个类的实例但是,为了正确测试类中的函数,我需要将属性设置为模拟服务而不是null。

我认为我需要做这样的事情:dynamicDataSource = new DynamicDataSource(null, mockMyService); 但是,尝试这样做会给我一个错误 Argument of type 'MockMyService' is not assignable to parameter of type 'MyService'. Type 'MockMyService' is missing the following properties from type 'MyService': baseURL, http, logging

我无法在 MockMyService 中设置这些属性,因为它们是私有属性。 我能够在组件测试中模拟这样的服务,所以我很困惑为什么我必须在这些模拟中拥有这些属性。

有没有更好的方法来测试这个类?如何使用模拟服务在测试中创建它的实例?

任何建议都会有很大帮助。

这是课程(顺便说一句):

export class DynamicDataSource implements DataSource<DynamicFlatNode>, OnDestroy {
 dataSubscription: Subscription;

  constructor(
    private _treeControl: FlatTreeControl<DynamicFlatNode>,
    private _database: MyService
  ) {}

  connect(collectionViewer: CollectionViewer): Observable<DynamicFlatNode[]> {...}

  disconnect(collectionViewer: CollectionViewer): void {}

 ...lots of functions and logic...

  ngOnDestroy(): void {
    this.dataSubscription?.unsubscribe();
  }
}

【问题讨论】:

  • 接受的答案有效,但我也被建议通过组件测试类中的方法(我在组件中使用它,并且我能够使用模拟制作类的实例服务)。不过,这不是直接的单元测试。因此,您必须在使用 as any 或通过组件进行测试之间做出选择。

标签: angular unit-testing angular-material angular9


【解决方案1】:

该错误不仅是因为缺少属性,还因为 class MockMyService 不是 class MyService

过去我也遇到过类似的情况。

我认为可能有几种方法可以实现这一点,但我发现最简单的方法可能就是利用 as any 的类型断言。

dynamicDataSource = new DynamicDataSource(null, mockMyService as any)

如果您不存根/模拟 MyServiceDynamicDataSource 将调用/使用的属性,您仍然可能会遇到运行时错误。 但是通过模拟这将使您能够创建间谍来实现我认为您尝试测试的目标

class MockMyService {
 getData = jasmine.createSpy('getData'),
 logging = jasmine.createSpy('logging')
 ....

}

注意:在过去的项目中,这被视为有点 hacky,因为在某种程度上覆盖了 TS,但在某些地方测试覆盖率更重要。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多