无法使Jest测试通过Angular

时间:2019-01-10 18:59:16

标签: angular unit-testing mocking jestjs jqwidget

这看起来是如此简单,以至于我知道我一定做错了什么,但是我已经待了整整一天,仍然无法通过简单的测试。我的组件使用第三方库JQWidgets,部分问题是测试报告该库中的错误,但是测试失败的另一部分显然是我的模拟数据应该加载到组件的属性中没有进入那里。

我正在尝试使用Jest模拟,但是即使到目前为止我已经阅读了十多次文档,我仍然不确定我是否做对了。有时我需要一个间谍,有时我只想让模拟函数(通常是服务函数)返回一些伪数据。我觉得我可能只是不理解Jest的一些嘲笑魔术。

对于任何含糊之处,我深表歉意,希望我的工作中有人可以问我,但没有,所以我很谦虚地寻求帮助。

编辑:模拟整个服务,这似乎效果更好,因为通过了我的测试断言,但是由于第三方模块中的错误,测试仍然失败。我尝试添加NO_ERRORS_SCHEMA,但这没有帮助:

TypeError: bA.getPropertyValue is not a function
      at R (node_modules/jqwidgets-scripts/jqwidgets/jqxcore.js:14:36743)

组件的ngOnInit()

ngOnInit() {
    this._dataService.getData().subscribe(
      data => {
        this.populate(data); // <--this line appears not to be running, as this function populates this.source.localdata with this data
        this.dataAdapter = new jqx.dataAdapter(this.source);
      },
      error => {
        console.error(error);
      }
    );
  }

我的测试

import { ComponentFixture, TestBed, async } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { jqxGridComponent } from 'jqwidgets-scripts/jqwidgets-ts/angular_jqxgrid';
import { ProgressComponent } from './progress.component';
import { ProgressGridDataService } from './progress.service';
import { WorkingFileService } from 'src/app/services/working-file/working-file.service';
import { IProgressData } from './progress.interfaces';
import { of } from 'rxjs';

describe('ProgressComponent', () => {
  let component: ProgressComponent;
  let fixture: ComponentFixture<ProgressComponent>;

  class ProgressServiceSpy {
    testHistory: IProgressData = {
      recordId: 1,
      product: 'A',
    };
    getData = jest.fn().mockImplementation(() => of(Object.assign({}, this.testHistory)));

    restartLoad = jest.fn();
  }
  beforeEach(
    async(() => {
      TestBed.configureTestingModule({
        declarations: [ProgressComponent, jqxGridComponent],
        providers: [
          WorkingFileService,
          { provide: ProgressGridDataService, useValue: {} },
        ],
      })
      .overrideComponent(ProgressComponent, {
        set: {
          providers: [
            { provide: ProgressGridDataService, useClass: ProgressServiceSpy },
          ],
        },
      })
      .compileComponents();
      fixture = TestBed.createComponent(ProgressComponent);
      component = fixture.componentInstance;
      fixture.detectChanges();
    })
  );

  describe('retry button', () => {
    it('should call the restartLoad service and pass a record ID', () => {
      component.ngOnInit();
     expect(component.source).toHaveProperty('localdata');
      expect(component.source.localdata).toEqual(testHistory);
    });
  });
});

2 个答案:

答案 0 :(得分:0)

您应该从TestBed获取服务引用,然后对其进行模拟或SpyOn:

    import { ComponentFixture, TestBed } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { jqxGridComponent } from 'jqwidgets-scripts/jqwidgets-ts/angular_jqxgrid';
import { ProgressComponent } from './progress.component';
import { ProgressGridDataService } from './progress.service';
import { HttpClientTestingModule } from '@angular/common/http/testing';
import { HttpClient } from '@angular/common/http';
import { IProgressData } from './progress.interfaces';
import { of } from 'rxjs';

describe('ProgressComponent', () => {
  let component: ProgressComponent;
  let progressService: ProgressGridDataService;
  let fixture: ComponentFixture<ProgressComponent>;

  beforeEach(() => {
    TestBed.configureTestingModule({
      declarations: [ProgressComponent, jqxGridComponent],
      imports: [HttpClientTestingModule],
      providers: [ProgressGridDataService, WorkingFileService],
    });
    fixture = TestBed.createComponent(ProgressComponent);
    component = fixture.componentInstance;
    progressService = TestBed.get(ProgressGridDataService); // Here get the service
    fixture.detectChanges();
  });

  describe('component load', () => {
    let testHistory: IProgressData;

    beforeEach(() => {
      testHistory = {
        recordId: 1,
        product: 'A',
        fileId: 'A',     
      };
    });
    it('should pull the data from the service into a component property', () => {
     //I'm trying to use a Jest mock function, but I'm not sure I'm using it right 

  //Mock and Spy now....

      jest.spyOn(progressService, 'getData').mockImplementation(() => of(testHistory));
      component.ngOnInit();

      expect(component.source).toHaveProperty('localdata');
      expect(component.source.localdata).toEqual(testHistory)
      //would love to have an expectation that the service was called properly, but not sure how to do Jest spies on that function correctly.
       });
      });
    });

答案 1 :(得分:0)

我进一步研究了一下。我遵循Angular Stackblitz Hero app的示例,并完全嘲笑了我的整个服务,因为它并未真正受到测试。我不明白为什么必须使用init-main来设置间谍服务而不是仅在TestBed配置中进行设置,但是我认为这是因为我的组件在其自己的overrideComponent数组中拥有该服务({ {3}}。

对于奇怪的providers错误,docs使我处于正确的位置,以便我能够将此代码段添加到bA.getPropertyValue is not a function中,然后终于我的测试通过了!

我希望天知道我对用Jest在Angular中进行测试的了解,因为花了整整8个小时才使这个微小的测试运行并通过是我的应用程序如此缺乏测试覆盖范围的原因。< / p>

jestGlobalMocks.ts