使用 Karma Jasmine 在 Angular 的单元测试中无法读取未定义的 属性 'on'
Getting Cannot read property 'on' of undefined in Unit Testing in Angular using Karma Jasmine
在我的 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 属性 'on' of undefined while testing near this.socket.on in component.
您没有模拟 getSocketIOConnector
方法的 return 值。这就是你得到错误的原因。另外,在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)
);
}
));
});
单元测试结果:
在我的 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 属性 'on' of undefined while testing near this.socket.on in component.
您没有模拟 getSocketIOConnector
方法的 return 值。这就是你得到错误的原因。另外,在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)
);
}
));
});
单元测试结果: