【问题标题】:How do I mock a service dependency in Angular with Jasmine?如何使用 Jasmine 在 Angular 中模拟服务依赖项?
【发布时间】:2021-02-12 21:30:58
【问题描述】:

我已经在谷歌上搜索了一段时间,对于我认为非常琐碎的事情没有快速简洁的答案。

我有一个服务 serviceToTest,它有一个依赖 serviceDep,它是通过 Angular 的 DI 注入的。

服务看起来像这样

export class ServiceToTest {
    constructor(private _dep: ServiceDep){}

    serviceMethod() {};
}

我想对serviceMethod 方法进行单元测试,为此我需要实例化服务并模拟依赖项。除了允许服务的实例化之外,依赖项不需要做任何事情。我要测试的方法不需要执行依赖。

如何设置一个 mock 以满足服务的构造函数?

【问题讨论】:

  • angular.io/guide/… 使用 fakeAsync() 从依赖于异步测试的组件中读取
  • 好点,fakeAsync 用于您需要控制异步区域的情况。我认为 Jake 在这种情况下不需要使用它。

标签: javascript angular jasmine


【解决方案1】:

下面的一些选项。

选项一

Angular recommended way 是通过 间谍

it('should return value', () => {
  const serviceDepSpy = spyOn(Testbed.inject(ServiceDep), 'serviceMethod').returnValue(of(MOCK_VALUE));

  component.ngOnInit(); // assuming your method is called on init. 

  expect(serviceDepSpy).toHaveBeenCalled();
});

我引用:

首选间谍,因为它们通常是模拟服务的最简单方法。

这使您可以轻松地在单元测试级别(在您的每个测试中)进行模拟,并避免覆盖模拟的服务(如果您使用 useClass 方法,这很容易成为一个问题。

选项二

useClass

当您在每个测试用例中总是返回相同的值时,这往往会发挥最佳效果。。如果您在每次测试中需要不同的模拟值,我会选择间谍。

选项三

useValue 当您需要对值或导入的模拟对象进行硬编码并在所有测试用例中使用相同的模拟值时,这种方式效果最佳。像 useClass 一样,覆盖它可能很棘手。

【讨论】:

    【解决方案2】:

    您可以提供自己的模拟服务来代替实际服务:

    describe('ServiceToTest ', () => {
      beforeEach(() => TestBed.configureTestingModule({
        imports: [],
        providers: [{ provide: ServiceToTest, useClass: ServiceToTestMock }]
      }));
    

    【讨论】:

    • 但是我用什么来实例化 mock ServiceToTestMock 的实例呢?
    • @Jake12342134 它被注入代替ServiceToTest(你不需要实例),ServiceToTestMock 可以像class ServiceToTestMock{} 一样简单,如果你不需要任何实际的方法叫
    猜你喜欢
    • 2015-03-20
    • 1970-01-01
    • 2018-02-19
    • 1970-01-01
    • 2020-03-28
    • 2015-07-07
    • 2018-06-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多