【发布时间】:2018-06-27 22:31:37
【问题描述】:
运行 Angular/Jasmine/Karma,我有一个组件使用服务来设置 Observable 'items' 数组的值。我使用异步管道显示它。效果很好。
现在,我正在尝试设置一个单元测试并让它通过,但我不确定我是否正确地验证了 'items' 数组是否获得了正确的值。
这里是相关的组件 .html 和 .ts :
export class ViperDashboardComponent implements OnInit, OnDestroy {
items: Observable<DashboardItem[]>;
constructor(private dashboardService: ViperDashboardService) { }
ngOnInit() {
this.items = this.dashboardService.getDashboardItems();
}
}
<ul class="list-group">
<li class="list-group-item" *ngFor="let item of items | async">
<h3>{{item.value}}</h3>
<p>{{item.detail}}</p>
</li>
</ul>
还有我的 component.spec.ts:
beforeEach(() => {
fixture = TestBed.createComponent(ViperDashboardComponent);
component = fixture.componentInstance;
viperDashboardService =
fixture.debugElement.injector.get(ViperDashboardService);
mockItems = [
{ key: 'item1', value: 'item 1', detail: 'This is item 1' },
{ key: 'item2', value: 'item 2', detail: 'This is item 2' },
{ key: 'item3', value: 'item 3', detail: 'This is item 3' }
];
spy = spyOn(viperDashboardService, 'getDashboardItems')
.and.returnValue(Observable.of<DashboardItem[]>(mockItems));
});
it('should create', () => {
expect(component).toBeTruthy();
});
it('should call getDashboardItems after component initialzed', () => {
fixture.detectChanges();
expect(spy.calls.any()).toBe(true, 'getDashboardItems should be called');
});
it('should show the dashboard after component initialized', () => {
fixture.detectChanges();
expect(component.items).toEqual(Observable.of(mockItems));
});
具体来说,我想知道:
1) 我开始创建一个异步“it”测试,但当它不起作用时我感到很惊讶。当我使用异步数据流时,为什么同步测试有效?
2) 当我检查 component.items 与 Observable.of(mockItems) 的等价性时,我是否真的在测试这些值是否相等?还是我只是测试它们都是 Observables?有没有更好的办法?
【问题讨论】:
-
您还不需要异步测试,因为您的服务会立即返回一个可观察对象(应该如此 - 真正的值稍后出现)。模板中的异步管道是稍后获得真正价值的地方。所以现在你的测试只是测试代码的同步部分。稍后,如果您测试模板呈现项目的情况,您可能需要进行异步测试。
-
所以是的,您实际上只是在测试您是否正在返回一个 observable。我的猜测是
expect(component.items).toEqual(Observable.of(mockItems));通过,因为即使Observable.of(mockItems));是一个不同的对象引用,然后你的模拟返回的 observable,所有的属性可能是相等的,所以对象被认为是等效的。 -
感谢@FrankModica。好吧,这就是我害怕的。那么,有没有办法测试 Observable 最终会返回正确的数据呢?或者是测试模板呈现它的唯一解决方案,正如您上面建议的那样?我可以这样做,但似乎它不是孤立地测试。如果我的测试失败,我不知道是组件逻辑还是模板有问题,如果你明白我的意思的话。
-
您可以通过不使用
async过滤器来避免测试模板。相反,您可以订阅组件中的 observable,然后从那里取出项目。然后你可以四处寻找如何测试异步 observable 的返回值。 -
我曾考虑过,但我真的很喜欢使用异步管道。它似乎使代码更干净。我想知道我是否可以通过这种方式提取值:
component.items.toPromise().then(result => { expect(result).toEqual(mockItems); });
标签: angular unit-testing typescript jasmine karma-runner