在对 Angular 4 组件进行单元测试时,我陷入困境并不断出错。
这是我的组件:
order-detail.component.ts
@Component({
selector: 'order-detail',
templateUrl: 'order-detail.component.html',
providers: [OrderService]
})
export class OrderDetailComponent implements OnInit {
private order: Order;
constructor(
private orderService: OrderService,
private route: ActivatedRoute,
private router: Router
) {}
ngOnInit() {
this.getOrder();
}
private getOrder(): void {
this.route.paramMap
.map((params: ParamMap) => {
if (+params.get('id') === 0) {
this.router.navigateByUrl('/404', {skipLocationChange: true});
}
return params;
})
.switchMap((params: ParamMap) => this.orderService.getOrder(+params.get('id')))
.subscribe((order: Order) => this.order = order);
}
}
这是一项服务:
order.service.ts
@Injectable()
export class OrderService {
private ordersUrl = `${environment.apiUrl}/orders/`;
constructor(private http: HttpClient) {}
getOrder(id: number): Observable<Order> {
return this.http.get(`${this.ordersUrl}${id}/`)
.map(response => response as Order);
}
}
我想在 OrderServive
上设置一个 spy 并使用这样的测试对其进行单元测试:
order-detail.component.spec.ts
describe('Order detail component', () => {
let fixture: ComponentFixture<OrderDetailComponent>;
let page: Page;
let activatedRoute: ActivatedRouteStub;
const fakeOrder: Order = {
id: 1,
title: 'Test 1',
contractor: {title: 'Contractor 1'} as Contractor,
} as Order;
class Page {
orderSpy: jasmine.Spy;
routerSpy: jasmine.Spy;
title: HTMLElement;
constructor() {
const orderService = fixture.debugElement.injector.get(OrderService);
this.orderSpy = spyOn(orderService, 'getOrder').and.returnValue(Observable.of(fakeOrder));
}
}
function createComponent() {
fixture = TestBed.createComponent(OrderDetailComponent);
page = new Page();
fixture.detectChanges();
return fixture.whenStable().then(() => {
fixture.detectChanges();
});
}
beforeEach(() => {
activatedRoute = new ActivatedRouteStub();
});
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [OrderDetailComponent],
imports: [RouterTestingModule, HttpClientTestingModule],
providers: [
OrderService,
{provide: ActivatedRoute, useValue: activatedRoute},
{provide: Router, useClass: RouterStub},
],
schemas: [NO_ERRORS_SCHEMA],
}).compileComponents();
}));
describe('when navigate with existing id', () => {
beforeEach(async(() => {
activatedRoute.testParamMap = {id: fakeOrder.id};
createComponent();
}));
it('should show title', () => {
expect(page.orderSpy).toHaveBeenCalledWith(fakeOrder.id);
});
});
});
但我不断收到此错误:TypeError:无法读取未定义的属性“订阅”
我从 Agular 文档中获取了 ActivatedRouteStub
和测试结构:https://angular.io/guide/testing
组件的代码可以很好地处理来自后端的真实数据并显示顺序。
我的代码库也包含类似的测试,它在具有类似服务的另一个组件上成功执行了相同的操作,因此该测试是唯一失败的地方。
使用 Angular 4.3.6、Karma 1.7.1 和 Jasmine 2.6.4。
可能会出现什么问题以及如何消除此错误?
最佳答案
经过一番研究,我实际上找出了导致错误的原因。我删除了
{provide: Router, useClass: RouterStub},
错误消失了。测试现在可以在没有此 stub 的情况下完美运行。
不确定问题是什么,但我认为文档中的 RouterStub
类缺少一些必要内容的实现。类(class)是从这里获取的:
https://angular.io/guide/testing#test-a-routed-component
https://angular.io/generated/live-examples/testing/app-specs.eplnkr.html
关于Angular 4单元测试错误 "TypeError: Cannot read property '订阅'未定义”,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46062481/