Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Intermittent error cannot match any routes unit testing Angular

I've read many posts on the subject about using the router testing module and trying to spy on the router.navigate method but none have resolved the issue I have. Every 2nd run of my tests or so I will see the error, here's the first line in full

Uncaught Error: Uncaught (in promise): Error: Cannot match any routes. URL Segment: 'post/view'

To reiterate the error has not been seen when I run my app only when testing

It only appears once no matter how many tests are in the component and it's always the first test that it happens for, if I switch the order then it's the new first test that fails with this error

My component is as follows ( unrelated code removed for brevity )

export class CreatePostComponent implements OnInit {

  constructor(private postService: PostService,
              private router: Router,
              private location: Location) {
  }

  submitPost() {
    this.validMessage = '';
    if (!this.createPostForm.valid) {
      this.validMessage = 'Please fill out the form before submitting!';
      return;
    }
    const post = this.createPostForm.value as IPost;
    this.postService.createPost(post)
      .pipe(first())
      .subscribe(
        data => {
          this.createPostForm.reset();

          //Here's the call that I believe causes the issues
          this.router.navigate(['post/view']);
        },
        error => {
          return throwError(error);
        }
      );
  }
}

Here's the spec, again unrelated tests removed

describe('CreatePostComponent', () => {
  let component: CreatePostComponent;
  let fixture: ComponentFixture<CreatePostComponent>;
  let http: HttpTestingController;
  let mockPostService;
  let mockLocationService;


  beforeEach(async(() => {
    mockPostService = jasmine.createSpyObj(['createPost']);
    mockLocationService = jasmine.createSpyObj(['back']);
    TestBed.configureTestingModule({
      declarations: [CreatePostComponent],
      imports: [ReactiveFormsModule,
        HttpClientTestingModule,
        RouterTestingModule],
      providers: [
        {provide: PostService, useValue: mockPostService},
        {provide: Location, useValue: mockLocationService}]
    })
      .compileComponents();
  }));

  beforeEach(() => {
    http = TestBed.get(HttpTestingController);
    fixture = TestBed.createComponent(CreatePostComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });

  it('should create', () => {
    expect(component).toBeTruthy();
  });

I have also tried spying on the router as below (rest of code unchanged)

  beforeEach(async(() => {
    mockPostService = jasmine.createSpyObj(['createPost']);
    mockLocationService = jasmine.createSpyObj(['back']);
    TestBed.configureTestingModule({
      declarations: [CreatePostComponent],
      imports: [ReactiveFormsModule,
        HttpClientTestingModule,
        RouterTestingModule],
      providers: [
        {provide: PostService, useValue: mockPostService},
        {provide: Location, useValue: mockLocationService}]
    })
      .compileComponents();

    spyOn<any>(component['router'], 'navigate').and.returnValue(true);
  }));

and I have tried injecting my own mock for navigate as below

  beforeEach(async(() => {
    mockPostService = jasmine.createSpyObj(['createPost']);
    mockLocationService = jasmine.createSpyObj(['back']);
    TestBed.configureTestingModule({
      declarations: [CreatePostComponent],
      imports: [ReactiveFormsModule,
        HttpClientTestingModule],
      providers: [
        {provide: PostService, useValue: mockPostService},
        {provide: Location, useValue: mockLocationService},
        {provide: Router, useValue: {navigate: () => true}}]
    })
      .compileComponents();
  }));
like image 683
LiamRyan Avatar asked Dec 17 '22 17:12

LiamRyan


1 Answers

You did not provide the RouterTestingModule with any valid routes, so it is telling you it has no idea how to route to 'post/view'. Change your import of RouterTestingModule to something like the following:

RouterTestingModule.withRoutes([
  { path: 'post/view', component: BlankComponent },
])

Where BlankComponent is an empty component just for testing purposes.

Here is a working StackBlitz showing this solution. To recreate your error, simply comment out the RouterTestingModule declaration I changed, and uncomment out the original one without routes just below it in the Stackblitz.

I agree the docs are not great on this - the main testing documentation simply states there will be a future document describing the RouterTestingModule in more detail. See the API info here, it gives an example at the end of the usage withRoutes.

I hope this helps. :)

like image 133
dmcgrandle Avatar answered Dec 28 '22 09:12

dmcgrandle