I am stuck and keep getting error while unit testing an Angular 4 component.
Here's my component:
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);
}
}
And here is a service:
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);
}
}
And I want to set a spy on OrderServive and unit test it with such test:
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);
});
});
});
But I keep getting this error: TypeError: Cannot read property 'subscribe' of undefined
I took ActivatedRouteStub and test structure from Agular documentation: https://angular.io/guide/testing
Component's code works fine with real data from backend and shows me order.
Also my codebase contains similar test which successfully does the same thing on another component with similar service, so this test is the only place which fails.
Using Angular 4.3.6, Karma 1.7.1 and Jasmine 2.6.4.
What could go wrong and how to get rid of this error?