我有一个服务SmsService
,该服务会在组件的submit()
方法内返回一个承诺。
在我的组件中,我从SmsService调用this.sms.send()
方法,并附加then()
和catch()
:this.sms.send(this.messageInput).then(....).catch(....)
在调用expect(smsSpy.send).toHaveBeenCalledWith(component.messageInput)
之后,this.sms.send()
的断言可以正常工作,但是this.messageInput
不会重置为null并且断言失败。我究竟做错了什么?我没有正确运行变更检测吗?
我正在尝试编写一些测试,以确保根据我的then
间谍返回的Promise分别调用组件中的catch
和send()
。我该怎么办? 。
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import {MomentModule} from 'angular2-moment'
import { FormsModule } from '@angular/forms';
import { AngularFirestore } from '@angular/fire/firestore';
import { Observable, of } from "rxjs";
import { ActivatedRoute } from '@angular/router';
import {SmsService} from './sms.service'
//my component
import {
Component,
OnInit,
AfterViewChecked,
ViewChild,
ElementRef,
AfterViewInit
} from "@angular/core";
@Component({
selector: "app-sms",
templateUrl: "./sms.component.pug",
styleUrls: ["./sms.component.scss"]
})
export class SmsComponent {
@ViewChild("scrollMe") private myScrollContainer: ElementRef;
public messageInput;
public list;
public err;
constructor(public sms: SmsService, private route:ActivatedRoute) {
this.list = this.sms.getItems()//this.route.data['value']['messages']
}
submit() {
this.sms
.send(this.messageInput)
.then(res => {
// console.log(res);
this.messageInput = null
})
.catch(err => {
this.err = `Could not send - ${err}`
});
}
}
//my test
describe('SmsComponent', () => {
let component: SmsComponent;
let fixture: ComponentFixture<SmsComponent>;
var afSpy = jasmine.createSpyObj('AngularFirestore', ['collection', 'valueChanges', 'snapshotChanges', 'pipe', 'add']);
var smsSpy = jasmine.createSpyObj('SmsService', ['send', 'then','catch']);
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ SmsComponent ],
providers:[
{ provide: SmsService, useValue: smsSpy },
{ provide: AngularFirestore, useValue: afSpy },
{
provide: ActivatedRoute, useValue: {
params: of([{ id: 'test' }])
}
}
],
imports:[MomentModule, FormsModule],
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(SmsComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('expect err', () => {
smsSpy.send.and.returnValue(Promise.resolve('asdf'));
smsSpy.catch.and.returnValue('caught');
component.messageInput = 'my new message'
component.submit()
fixture.detectChanges();
expect(smsSpy.send).toHaveBeenCalledWith(component.messageInput) //<-- this passes
expect(component.messageInput).toBe(null) //<---- this fails
});
});
答案 0 :(得分:0)
您的服务没有任何then
或catch
方法。它只有一个send()
方法,该方法返回Promise。返回的Promise是具有then和catch方法的对象。所以这行毫无意义:
var smsSpy = jasmine.createSpyObj('SmsService', ['send', 'then','catch']);
您需要使间谍返回承诺,并且需要控制异步,例如通过使用fakeAsync()
。
这是一个几乎与您匹配的完整示例(我只保留了重要部分):
组件:
import { Component } from '@angular/core';
import { SmsService } from '../sms.service';
@Component({
selector: 'app-sms',
templateUrl: './sms.component.html',
styleUrls: ['./sms.component.scss']
})
export class SmsComponent {
public messageInput: string;
constructor(private sms: SmsService) { }
submit() {
this.sms
.send(this.messageInput)
.then(res => {
this.messageInput = null;
});
}
}
测试:
import { fakeAsync, TestBed, tick } from '@angular/core/testing';
import { SmsComponent } from './sms.component';
import { SmsService } from '../sms.service';
describe('SmsComponent', () => {
let component: SmsComponent;
beforeEach(() => {
TestBed.configureTestingModule({
declarations: [ SmsComponent ]
});
});
beforeEach(() => {
component = TestBed.createComponent(SmsComponent).componentInstance;
});
it('should sublut and clear', fakeAsync(() => {
// obtain the service injected in the component by Angular
const smsService: SmsService = TestBed.get(SmsService);
// spy on its send method, and make it return a resolved promise
spyOn(smsService, 'send').and.returnValue(Promise.resolve('hello world'));
// set the message input in the component
component.messageInput = 'world';
// call submit()
component.submit();
// check that the service call has been made
expect(smsService.send).toHaveBeenCalledWith('world');
// tick in order to trigger the execution of the then callback registered on the promise
tick();
// check that the callback has rset the messageInput to null
expect(component.messageInput).toBeNull();
}));
});