代码之家  ›  专栏  ›  技术社区  ›  redOctober13

无法通过Jest测试

  •  -1
  • redOctober13  · 技术社区  · 6 年前

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

    我试着用玩笑式的嘲弄,但是尽管我已经把文档读了十几遍了,我还是不确定我做得对不对。有时我需要一个间谍,有时我只希望模拟函数(通常是服务函数)返回一些伪数据。我觉得我只是不懂一些戏谑的魔术。

    编辑:模拟整个服务 这看起来工作得更好,因为我的测试断言通过了,但是由于第三方模块中的错误,测试仍然失败。我尝试过添加“无错误”模式,但没有帮助:

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

    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 回复  |  直到 6 年前
        1
  •  1
  •   redOctober13    6 年前

    我通过进一步的挖掘设法弄明白了。我以 Angular Stackblitz Hero app overrideComponent 设置spy服务而不是仅仅在TestBed配置中这样做,但我认为这是因为我的组件有自己的服务 providers docs

    奇怪的是 bA.getPropertyValue is not a function 错误, this Github issue 把我放在正确的轨道上,这样我就可以把这个片段添加到 jestGlobalMocks.ts

    我真希望我能更清楚地知道我在用Angular with Jest进行测试,因为花了整整8个小时来运行和通过这个微小的测试,这正是我的应用程序如此缺乏测试覆盖率的原因。

    Object.defineProperty(window, 'getComputedStyle', {
      value: () => ({
        getPropertyValue: prop => {
          return '';
        },
      }),
    })
    
        2
  •  -1
  •   nircraft    6 年前

    您应该从TestBed获取服务引用,然后模拟或监视它:

        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.
           });
          });
        });