【问题标题】:Getting Cannot read property 'on' of undefined in Unit Testing in Angular using Karma Jasmine使用 Karma Jasmine 在 Angular 的单元测试中无法读取未定义的属性“on”
【发布时间】:2020-12-15 08:11:02
【问题描述】:

在我的 component.ts 文件中,我有一个名为“socketService”的服务,我在其中使用套接字,在组件中,我有一行

this.socket = this.socketService.getSocketIOConnector(this.data.product)
this.socket.on('connected', (message: string) => {
    this.connectionMsg = message
})

在我的 spec.ts 文件中,我有

beforeEach(async(() => {
  fixture = TestBed.createComponent(OndemandComponent);
  component = fixture.componentInstance;
  fixture.detectChanges();
}));
it("should check socket service", inject([SocketioService], (socketioService: SocketioService) => {
  socketioService = TestBed.get(SocketioService);
  const spy = spyOn(socketioService, "getSocketIOConnector");
  expect(spy).toHaveBeenCalled();
}));
it("should create", () => {
  expect(component).toBeTruthy();
});

它给了我 TypeError: Cannot read property 'on' of undefined while testing near this.socket.on in component.

【问题讨论】:

  • 嗨!首先,你能把整个代码吗?您是否定义了 component.data.product 属性?稍后,如果您使用 inject() 方法,则不需要使用 TestBed.get()。它们都应该是同一个实例。所以我建议你只使用一个。另外,您可以使用 TestBed.inject() 方法来代替 socketioService = TestBed.inject(SocketioService); 希望它有所帮助。
  • @lorenago 感谢您的指出。那是我的错误,我忘记移除 TetBed。但我仍然遇到同样的错误
  • 请告诉我们你是怎么打电话给TestBed.configureTestingModule(..)的。
  • 您在哪里打电话给this.socket.onconstructorngOnInit
  • @slideshowp2 在 ngOnInit 中调用它

标签: angular typescript unit-testing socket.io karma-jasmine


【解决方案1】:

您没有模拟getSocketIOConnector 方法的返回值。这就是你得到错误的原因。另外,在mock之后需要调用fixture.detectChanges();来触发组件的ngOnInit方法。

这是一个使用 angular v11+ 的工作示例:

ondemand.component.ts:

import { Component, OnInit } from '@angular/core';
import { SocketService } from './socket.service';

@Component({})
export class OndemandComponent implements OnInit {
  socket: SocketService;
  data = {
    product: 'real product',
  };
  connectionMsg: string;
  constructor(private socketService: SocketService) {}
  ngOnInit() {
    this.socket = this.socketService.getSocketIOConnector(this.data.product);
    this.socket.on('connected', (message: string) => {
      this.connectionMsg = message;
    });
  }
}

socket.service.ts:

import { Injectable } from '@angular/core';

@Injectable()
export class SocketService {
  getSocketIOConnector(params) {
    return this;
  }
  on(event, listener) {}
}

ondemand.component.spec.ts:

import { ComponentFixture, inject, TestBed } from '@angular/core/testing';
import { OndemandComponent } from './ondemand.component';
import { SocketService } from './socket.service';

fdescribe('65302152', () => {
  let fixture: ComponentFixture<OndemandComponent>;
  let component: OndemandComponent;
  beforeEach(() => {
    TestBed.configureTestingModule({
      declarations: [OndemandComponent],
      providers: [SocketService],
    }).compileComponents();
    fixture = TestBed.createComponent(OndemandComponent);
    component = fixture.componentInstance;
  });
  it('should create', () => {
    expect(component).toBeTruthy();
  });

  it('should check socket service', inject(
    [SocketService],
    (socketioService: SocketService) => {
      const connectorSpy = jasmine.createSpyObj('connector', ['on']);
      connectorSpy.on.and.callFake((event, listener) => {
        listener('fake message');
      });
      const getSocketIOConnectorSpy = spyOn(
        socketioService,
        'getSocketIOConnector'
      ).and.returnValue(connectorSpy);

      // trigger ngOnInit of component
      fixture.detectChanges();

      expect(getSocketIOConnectorSpy).toHaveBeenCalledOnceWith('real product');
      expect(connectorSpy.on).toHaveBeenCalledOnceWith(
        'connected',
        jasmine.any(Function)
      );
    }
  ));
});

单元测试结果:

【讨论】:

    猜你喜欢
    • 2020-05-25
    • 2018-02-02
    • 2018-12-23
    • 2023-03-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-09
    • 2020-07-19
    相关资源
    最近更新 更多