I'm trying to unit test a (angular 2) component with routerLink
and routerLinkActive
but all test cases fail with following error message. (Note: I have stubbed the router and other related dependencies. Here's the reference that I used for the same.).
Cannot read property 'subscribe' of undefined
I have also noticed that when routerLink
and routerLinkActive
are removed from my template, all test cases will run without any errors.
I think the error is caused by either RouterTestingModule
or SharedModule
(contains component for displaying and validating password input field). So I tried removing or adding them to find which is actually causing the problem. Here's what I observed.
- I get '
Cannot read property 'subscribe' of undefined'
ifRouterTestingModule
orSharedModule
is present. - I do not get any error linked to router only if I remove both
RouterTestingModule
andSharedModules
but the elements from theSharedModules
would not get loaded in the component and some test cases still fail because of that.
TestBed configuration:
TestBed.configureTestingModule({
imports: [CoreModule,SharedModule,RouterTestingModule],
declarations: [ MyComponent,RouterLinkStubDirective,RouterOutletStubComponent ],
providers: [
FormBuilder,
{ provide: Router, useClass: RouterStub },
{ provide: ActivatedRoute, userClass: ActivatedRouteStub}
],
schemas: [NO_ERRORS_SCHEMA]
})
.overrideComponent(MyComponent, {
set: {
providers: [
{provide: AuthModel, useClass: MockAuthModel}
],
}
})
.compileComponents();
}));
ActivatedRouterStub:
@Injectable()
export class ActivatedRouteStub {
// ActivatedRoute.params is Observable
private subject = new BehaviorSubject(this.testParams);
params = this.subject.asObservable();
// Test parameters
private _testParams: {};
get testParams() { return this._testParams; }
set testParams(params: {}) {
this._testParams = params;
this.subject.next(params);
}
// ActivatedRoute.snapshot.params
get snapshot() {
return { params: this.testParams };
}
}
What changes should I make to solve the issue?
I have managed to solve this issue. I'll list what changes I made to solve the issue.
As I mentioned in the comments,
routerLink
works only on real router. So we need to include RouterTestingModule (include.withRoutes([{path: 'some/path',component: someComponent}])
if you plan to click on it while testing).We need not provide Router dependencies separately if we have added
RouterTestingModule
already. So I removed bothRouter
andActivatedRoute
dependency that I provided. Now, the error changed fromCannot read property 'subscribe' of undefined
toCannot read property 'outlets' of null
.I found out this error occurs when the
routerLink
is pointing to a null variable. In my case, the property calledfavoriteUrl
that i assigned torouterLink
was null because of the isolated testing environment. So I manually assigned a value to the property inbeforeEach
function and that solved the problem, atleast for me.
Thanks to everyone who tried to help! :-)
References:
Angular has no way of knowing that you want it to use the activatedRoute variable that you created yourself(as per comment) so it will create default one and use that in DI. Instead of the current setup for the ActivatedRoute dependency use { provide: ActivatedRoute, useValue: mockInstance}
where mockInstance
is a mock of ActivatedRoute
, you can create that with jasmine.createSpyObj
来源:https://stackoverflow.com/questions/46319449/how-to-correctly-use-sharedmodules-with-router-while-testing-angular-2-applicati