我正在尝试进行组件集成测试(即包括Angular生命周期事件),但我很难用Jasmine模拟服务,这是一个公开Subscribable
的服务。 / p>
重现我的场景:
ng new ng-comp-tests
ng generate component my-screen
ng generate service crud
ng generate class item
将课程更新为:
export class Item {
constructor(public name: string) { }
}
然后使服务看起来像这样:
export class CrudService {
private thing = new Subject<Item>();
constructor() {
setInterval(() => { this.thing.next(new Item('Thing ' + Math.random())); }, 1000);
}
getThingObservable() {
return this.thing.asObservable();
}
}
将组件更改为此类(并将其作为应用程序组件中的主要内容):
<p *ngIf="!!thing">{{thing.name}}</p>
export class MyScreenComponent implements OnInit, OnDestroy {
public thing: Item;
private thingSubscription: Subscription;
constructor(private service: CrudService) { }
ngOnInit() {
this.thingSubscription = this.service
.getThingObservable()
.subscribe(t => { this.thing = t; });
}
ngOnDestroy(): void {
this.thingSubscription.unsubscribe();
}
}
最后,将规格更改为:
describe('MyScreenComponent', () => {
let component: MyScreenComponent;
let fixture: ComponentFixture<MyScreenComponent>;
beforeEach(async(() => {
const serviceSpy = jasmine.createSpyObj('CrudService', {
getThingObservable: () => new Subject<Item>().asObservable()
});
TestBed.configureTestingModule({
declarations: [ MyScreenComponent ],
providers: [ { provide: CrudService, useValue: serviceSpy } ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(MyScreenComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
这将为测试提供例外:
MyScreenComponent应该创建
[object ErrorEvent] thrown
例外情况并非如此有用,Chrome的控制台也不是,因为它显示了这个缩写日志:
top answer for a related question建议我忘记执行fixture.detectChanges()
(这会阻止ngOnInit
解雇),但正如您所见,我的代码中确实存在此问题。
这里肯定有其他问题,但是什么?
答案 0 :(得分:0)
答案在the jasmine.createSpyObj(...)
documentation,说明第二个参数(强调我的):
用于创建间谍的方法名称数组,或对象,其键将是方法名称,并且值为returnValue 。
在您的代码中,您为此getThingObservable
提供了一个假实现:
getThingObservable: () => new Subject<Item>().asObservable()
有了这个,getThingObservable
间谍会在组件调用它时返回一个lambda ,它没有subscribe
组件试图做的事情,所以{{1完全失败了。 ngOnInit
仅作为辅助效果失败。
您应该直接传递returnValue,如下所示:
ngOnDestroy
然后,当组件调用getThingObservable: new Subject<Item>().asObservable()
时,它将获得一个实际的可观察量,并且事情会没事。
PS。您还可以简化使用getThingObservable
:
{ of } from 'rxjs/observable/of'
最后,您还可以使用marble tests来更好地控制测试中的可观察对象。