【发布时间】:2020-09-10 06:55:04
【问题描述】:
我正在尝试使用 Jasmine 在一些示例之后第一次实现 Angular 单元测试,但我发现了一些问题。
所以我有这个 PeopleListComponent 类来实现组件的逻辑:
import { Component, OnInit, ElementRef, ViewChild } from '@angular/core';
import { EventService } from '../event.service';
import interactionPlugin, { Draggable } from '@fullcalendar/interaction';
interface WorkShiftTypes {
name: string;
value: string;
}
@Component({
selector: 'app-people-list',
templateUrl: './people-list.component.html',
styleUrls: ['./people-list.component.css']
})
export class PeopleListComponent implements OnInit {
people: any[];
//cities: City[];
workShiftTypes: WorkShiftTypes[];
selectedShift: WorkShiftTypes;
@ViewChild('draggable_people') draggablePeopleExternalElement: ElementRef;
constructor(private eventService: EventService) { }
ngOnInit(): void {
this.eventService.getPeople().then(people => {this.people = people;});
this.selectedShift = {name: 'Mattina', value: 'Mattina'};
this.workShiftTypes = [
{name: 'Mattina', value: 'Mattina'},
{name: 'Pomeriggio', value: 'Pomeriggio'},
{name: 'Notte', value: 'Notte'},
{name: 'Custom', value: 'Custom'}
];
}
ngAfterViewInit() {
console.log("PEOPLE LIST ngAfterViewInit() START !!!")
var self = this
new Draggable(this.draggablePeopleExternalElement.nativeElement, {
itemSelector: '.fc-event',
eventData: function(eventEl) {
console.log("DRAG !!!");
//console.log("SELECTED SHIFT: " + self.selectedShift.value);
return {
title: eventEl.innerText,
startTime: "17:00",
duration: { hours: 8 }
};
}
});
}
createEventObject() {
return 1;
}
}
如您所见,它包含这个非常简单的 createEventObject() 方法,目前只返回 1(我想尽可能简单)。我的第一个单元测试必须测试这个方法,只需检查返回值是否为 1。
如您所见,前面的方法需要一个 EventService 服务实例注入到构造函数中。
这是 EventServive 类代码:
import { Injectable } from '@angular/core';
//import { Http } from '@angular/http';
import { HttpClientModule, HttpClient } from '@angular/common/http'
@Injectable()
export class EventService {
private events = [
{id: 1, title: 'All Day Event', start: '2017-02-01'},
{id: 2, title: 'Long Event', start: '2017-02-07', end: '2017-02-10'},
{id: 3, title: 'Repeating Event', start: '2017-02-09T16:00:00'},
];
private people = [
{id: 1, name: "PERSONA 1"},
{id: 2, name: "PERSONA 2"},
{id: 3, name: "PERSONA 3"},
{id: 4, name: "PERSONA 4"},
{id: 5, name: "PERSONA 5"},
]
constructor(private http: HttpClient) {}
/*
getEvents(): Promise<any[]> {
return this.http.get('assets/json_mock/calendarevents.json')
.toPromise()
.then(res => JSON.parse(JSON.stringify(res)).data)
.then(res => {
console.log(res);
// you returned no value here!
return res;
})
}
*/
getEvents(): Promise<any[]> {
return Promise.all(this.events)
.then(res => {
console.log(res);
// you returned no value here!
return res;
})
}
addEvent(event) {
//this.events.push(event);
//console.log("EVENT:")
//console.log(event.event.title);
console.log(event.event.start);
console.log(event);
const newEvent = {id: 5, title: event.event.title, start: event.event.start, end: event.event.end};
this.events.push(newEvent);
console.log(this.events);
}
getPeople(): Promise<any[]> {
return Promise.all(this.people)
.then(res => {
console.log(res);
return res;
})
}
}
如您所见,此方法本身将另一个对象注入构造函数(HttpClient 执行 HTTP 请求)。
好的,现在我想在我的单元测试中实现 createEventObject() 方法测试。所以我有这个 people-list.component.spec.ts 文件:
import {async, ComponentFixture, TestBed} from '@angular/core/testing';
import { PeopleListComponent } from "./people-list.component"
import { EventService } from '../event.service';
import {HttpClientTestingModule} from '@angular/common/http/testing';
describe('people-list', () => {
let component: PeopleListComponent;
let fixture: ComponentFixture<PeopleListComponent>;
let eventServiceSpy : jasmine.SpyObj<EventService>;
beforeEach(async(() => {
const eventServiceSpyObj = jasmine.createSpyObj('EventService',['getPeople'])
TestBed.configureTestingModule({
declarations: [PeopleListComponent],
imports: [HttpClientTestingModule],
providers : [{ provide : EventService, useValue : eventServiceSpyObj }]
});
// Create a testing version of my PeopleListComponent:
fixture = TestBed.createComponent(PeopleListComponent);
eventServiceSpy = TestBed.inject(EventService);
component = fixture.componentInstance;
fixture.detectChanges();
}));
it('createEventObject() return 1', () => {
expect(component.createEventObject()).toBe(1)
})
})
我完全不确定它是否在逻辑上正确......
问题是目前IDE在这一行给我一个错误:
eventServiceSpy = TestBed.inject(EventService);
错误是:
Type 'EventService' is not assignable to type 'SpyObj<EventService>'.
Type 'EventService' is not assignable to type '{ getEvents: (() => Promise<any[]>) & Spy<() => Promise<any[]>>; addEvent: ((event: any) => void) & Spy<(event: any) => void>; getPeople: (() => Promise<any[]>) & Spy<...>; }'.
Types of property 'getEvents' are incompatible.
Type '() => Promise<any[]>' is not assignable to type '(() => Promise<any[]>) & Spy<() => Promise<any[]>>'.
Type '() => Promise<any[]>' is missing the following properties from type 'Spy<() => Promise<any[]>>': and, calls, withArgsts(2322)
怎么了?如何正确测试我的组件方法?
【问题讨论】:
-
您是否尝试过仅使用
any而不是 jasmine 的泛型类型,或者只是为这一行禁用 ts 编译器?
标签: angular unit-testing jasmine angular-unit-test