【问题标题】:Angular Testing - TypeError: Cannot read property '7' of undefined角度测试 - 类型错误:无法读取未定义的属性“7”
【发布时间】:2020-06-26 14:21:24
【问题描述】:

我是 Angular 测试的新手,我正在尝试使这个测试工作,但找不到解决这个问题的方法。如果有人有任何想法,请。

TypeError:无法读取未定义的属性“7” 在 在 AnaliseContasTitularComponent.ngOnInit (http://localhost:9876/karma_webpack/src/app/extratos-mensais-interno/analise-contas-titular/analise-contas-titular.component.ts:103: 2)

执行此命令执行测试:

ng 测试 --codeCoverage=true --progress=false --watch=false

我的测试单元文件:

import { Overlay } from '@angular/cdk/overlay';
import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
import { InjectionToken } from '@angular/core';
import { MAT_DIALOG_SCROLL_STRATEGY, MatDialog } from '@angular/material/dialog';
import { MatSnackBar } from '@angular/material/snack-bar';
import { RouterTestingModule } from '@angular/router/testing';
import { AnaliseContasTitularComponent } from './analise-contas-titular.component';

import { ExtratosMensaisInternoService } from '../extratos-mensais-interno.service';

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

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      imports: [ RouterTestingModule, HttpClientTestingModule ],
      declarations: [ AnaliseContasTitularComponent ],
      providers: [ MatDialog, Overlay, MatSnackBar,
        { provide: InjectionToken, useValue: {} },
        { provide: MAT_DIALOG_SCROLL_STRATEGY, useValue: {} },
      ]
    })
    .compileComponents();
  }));

  beforeEach(() => {
    fixture = TestBed.createComponent(AnaliseContasTitularComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });
  

  it('should create', () => {
    expect(component).toBeTruthy();
  });
});

.ts 文件中的 ngOnInit 方法:

ngOnInit(): void {
    const competencia: CompetenciaInterno = this.serv.getCompetenciaSelecionada();

    this.serv.getExtratoMensal(competencia[7]).subscribe((res: ExtratoMensalData) => {
      this.extratoMensal = res.data;
    }, (error: HttpErrorResponse) => {
      this.utils.showDialogError(error);
    });

  }

以及服务文件,使用 ngOnInit 调用的方法:

getCompetenciaSelecionada(): CompetenciaInterno {
    return JSON.parse(sessionStorage.getItem('competenciaInterno'));
  }

我在互联网上找不到以有效方式处理模拟数据的示例。

我只需要停止这个错误,因为我有多个文件出现同样的错误。让我继续进行其他测试。

谢谢

【问题讨论】:

    标签: angular testing mocking jasmine session-storage


    【解决方案1】:

    我假设getCompetenciaSelecionada 住在ExtratosMensaisInternoService,如果是这样,您必须模拟此服务。

    您可以附加 sessionStorage 中的项目,也许这会起作用,但我喜欢模拟外部依赖项。

    试试这个:

    // import of to be able to mock respond with an observable for getExtratoMensal
    import { of } from 'rxjs';
    import { Overlay } from '@angular/cdk/overlay';
    import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
    import { InjectionToken } from '@angular/core';
    import { MAT_DIALOG_SCROLL_STRATEGY, MatDialog } from '@angular/material/dialog';
    import { MatSnackBar } from '@angular/material/snack-bar';
    import { RouterTestingModule } from '@angular/router/testing';
    import { AnaliseContasTitularComponent } from './analise-contas-titular.component';
    
    import { ExtratosMensaisInternoService } from '../extratos-mensais-interno.service';
    
    describe('AnaliseContasTitularComponent', () => {
      let component: AnaliseContasTitularComponent;
      let fixture: ComponentFixture<AnaliseContasTitularComponent>;
      // create a mock, where the first string 'serv' is what you want the mock to be named.
      // and the array of strings are the public methods you would like to mock
      let mockExtratosMensaisInternoService = jasmine.createSpyObj('serv', ['getCompetenciaSelecionada', 'getExtratoMensal']);
    
      beforeEach(async(() => {
        TestBed.configureTestingModule({
          imports: [ RouterTestingModule, HttpClientTestingModule ],
          declarations: [ AnaliseContasTitularComponent ],
          providers: [ MatDialog, Overlay, MatSnackBar,
            { provide: InjectionToken, useValue: {} },
            { provide: MAT_DIALOG_SCROLL_STRATEGY, useValue: {} },
          // now that we are providing a mock for ExtratosMensaisInternoService, I think you can get rid of HTTPClientTestingModule import.
           { provide: ExtratosMensaisInternoService, useValue: mockExtratosMensaisInternoService },
          ]
        })
        .compileComponents();
      }));
    
      beforeEach(() => {
        fixture = TestBed.createComponent(AnaliseContasTitularComponent);
        component = fixture.componentInstance;
        mockExtratosMensaisInternoService.getCompetenciaSelecionada.and.returnValue([0, 1, 2, 3, 4, 5, 6, 7]); // you can mock the array to what you need, I assume you need at least 8 elements because of the 7.
        mockExtratosMensaisInternoService.getExtratoMensal.and.returnValue(of({ data: 'hello world' }));
        // mock the data to be whatever you would like.
        fixture.detectChanges();
      });
      
    
      it('should create', () => {
        expect(component).toBeTruthy();
      });
    });
    

    【讨论】:

    • 非常感谢。这完美无缺。我现在将研究此答案以解决其他文件。
    • 您好,您能帮我解决另一个问题吗?我有一个类似的组件,在 ngOnInit const compencia 上有这个: Competencia = this.serv.getCompetenciaSelecionada(); const titularidade = serventia.titularidade.substring(0, 1).toUpperCase();并且控制台一直说:TypeError:无法读取未定义的属性“子字符串”我找不到模拟有效属性的方法。尝试将数组用于 createSpyObj 上的属性,但它一直显示相同的错误。
    • 什么是serventia?似乎titularidade 未定义。如果您不介意,请创建一个包含更多详细信息的新问题并将链接发送给我,让我看看是否可以提供帮助。
    • 当然。我很抱歉打扰。 :/ 这里是。 stackoverflow.com/questions/62876364/…提前感谢您花时间帮助我。
    猜你喜欢
    • 2020-05-09
    • 1970-01-01
    • 2018-12-04
    • 2019-04-28
    • 2019-11-16
    • 2020-11-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多