1

我该如何解决这个问题?

大家好,我对使用 karma 和 jasmine 对 Angular 6 进行单元测试非常陌生

我正在尝试覆盖组件构造函数内部但无法执行的服务。'it' 块 'should create component' 覆盖了构造函数内的行,但服务返回的数据除外。

组件.ts

  constructor(public firstService: FirstService, public secondService: SecondService) {

    let localData :any
    let id = this.secondService.getId()
    let initialId = this.secondService.getInitialId()

    this.firstService.getRevisions(id, initialId).subscribe((data) => {
      if (data && data.content) {
         localData = data.content || [];
      }
    });
    }

组件.spec.ts

 describe('TestComponent', () => {
      let component: TestComponent;
      let fixture: ComponentFixture<TestComponent>;
      let firstService: FirstService;
      let secondService: SecondService;

     beforeEach(() => {
      TestBed.configureTestingModule({
      declarations: [TestComponent],
      providers: [FirstService, SecondService]
     })
      .compileComponents();
     });
     beforeEach(() => {
     firstService = TestBed.get(FirstService);
     fixture = TestBed.createComponent(TestComponent);
     component = fixture.componentInstance;
     secondService = TestBed.get(SecondService);
     fixture.detectChanges();
     });

    it('should create Component', () => {
    expect(component).toBeTruthy();
    const mockData = {
      "content": [
        {
          "name": "String",
        }
      ],
    }
    spyOn(firstService, "getRevisions").and.callFake(() => {
      return of({ mockData });
    });
    spyOn(secondService, 'getId');
    spyOn(secondService, 'getInitialId');

    fixture.whenStable().then(() => {
      expect(firstService.getRevisions).toHaveBeenCalled();
    });
    });
4

1 回答 1

0

在调用构造函数后,您正在监视服务。

compileComponents()当在您的 TestBed 上调用该方法时,将调用构造函数。

所以你必须有可能:

首先,您可以创建一个存根服务,该服务已经返回一个特定的 observable,它发出一个值 X。然后,您将在您的 TestBed 中提供这个存根,{provide: YourService, useValue: serviceStub}其中 serviceStub 看起来像这样:const serviceStub = {yourMethod: ()=> of(YOUR_TEST_VALUE}

问题是,在您的测试用例中,您无法期望调用服务方法,但您可以测试,从您的 observable 发出的值设置在您的组件中。此外,如果您想为不同的用例更改值 X,则需要创建多个描述,每个描述提供不同版本的服务模拟。

恕我直言,更好的方法是将订阅移动到 onInit 生命周期钩子中。

对于您的应用程序,它不会产生影响,并且更容易测试。

第一次触发时调用测试中的 onInit 生命周期fixture.detectChanges

话虽如此,如果您将订阅移动到 ngOnInit 方法中,您只需要从 beforeEach 函数中删除并在您的 spyOn之后fixture.detectChanged将其移动到您的测试用例中。

于 2019-06-18T19:20:31.153 回答