如何使用Jasmine模拟Angular中的服务依赖关系?

时间:2020-10-30 12:05:45

标签: javascript angular jasmine

我已经使用谷歌搜索了一段时间了,对于我认为微不足道的某些事情,没有一个简洁的答案。

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

服务看起来像这样

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

    serviceMethod() {};
}

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

如何设置一个模拟,以便满足服务的构造函数?

2 个答案:

答案 0 :(得分:0)

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

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

答案 1 :(得分:0)

下面的一些选项。

选项一

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一样,覆盖起来可能很棘手。