预期的间谍导航已被调用

Expected spy navigate to have been called

我在用户登录我的 angular 应用程序 (Angular 8) 后创建了一条路线。现在我正在尝试编写一个测试用例。但它给出了以下错误。

路由(/profile)页面无法调用。

Expected spy navigate to have been called with:
  [ [ '/profile' ] ]
but it was never called.

login.component.js

import { Component, OnInit } from '@angular/core';
import { UserService } from '../../services/user.service';
import { User } from '../../models/user';
import { Router } from '@angular/router';

@Component({
  selector: 'app-login',
  templateUrl: './login.component.html',
  styleUrls: ['./login.component.css']
})
export class LoginComponent implements OnInit {

  user: User = new User();
  errorMessage: string;
  

  constructor(private userService: UserService, private router: Router){ }

  ngOnInit(): void {
    if(this.userService.currentUserValue){
      this.router.navigate(['/home']);
      return;
    }
  }

  login() {
    this.userService.login(this.user).subscribe(data => {
      this.router.navigate(['/profile']);
    }, err => {
      this.errorMessage = "Username or password is incorrect.";
    });
  }

}

login.component.spec.ts

import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
import { LoginComponent } from './login.component';
import { UserService } from 'src/app/services/user.service';
import { Router } from '@angular/router';
import { FormsModule } from '@angular/forms';
import { ExpectedConditions } from 'protractor';
import { DebugElement } from '@angular/core';
import { RouterTestingModule } from '@angular/router/testing';
import { HomeComponent } from '../home/home.component';
import { ProfileComponent } from '../profile/profile.component';

describe('LoginComponent', () => {
  let component: LoginComponent;
  let fixture: ComponentFixture<LoginComponent>;
  let debugElement: DebugElement;
  let location, router: Router;
  let mockRouter;


  beforeEach(async(() => {
    TestBed.configureTestingModule({
     
      imports: [ HttpClientTestingModule, FormsModule ],
      declarations: [ LoginComponent, ProfileComponent ],
      providers: [UserService]
    })
    .compileComponents();
  }));

  beforeEach(() => {
    mockRouter = { navigate: jasmine.createSpy('navigate') };
    TestBed.configureTestingModule({
        imports: [RouterTestingModule.withRoutes([
            { path: 'profile', component: ProfileComponent }
        ])],
        declarations: [LoginComponent, ProfileComponent],
        providers: [
            { provide: Router, useValue: mockRouter},
        ]
    });
  });


  beforeEach(() => {
    fixture = TestBed.createComponent(LoginComponent);
    component = fixture.componentInstance;
    debugElement = fixture.debugElement;
});

it('should go profile ', async(() => {
  fixture.detectChanges();
  component.login();
  expect(mockRouter.navigate).toHaveBeenCalledWith(['/profile']);   
}));


});

你为什么configuringTestingModule两次?

你应该嘲笑 userService.

尝试:

import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
import { LoginComponent } from './login.component';
import { UserService } from 'src/app/services/user.service';
import { Router } from '@angular/router';
import { FormsModule } from '@angular/forms';
import { ExpectedConditions } from 'protractor';
import { DebugElement } from '@angular/core';
import { RouterTestingModule } from '@angular/router/testing';
import { HomeComponent } from '../home/home.component';
import { ProfileComponent } from '../profile/profile.component';
import { of } from 'rxjs'; // import of from rxjs
import { throwError } from 'rxjs'; // import throwError

describe('LoginComponent', () => {
  let component: LoginComponent;
  let fixture: ComponentFixture<LoginComponent>;
  let debugElement: DebugElement;
  let mockUserService = jasmine.createSpyObj('userService', ['login']);
  mockUserService.currentUserValue = /* mock currentUserValue to what it should be */
  let router: Router;

  beforeEach(async(() => {
    // I don't think you need HttpClientTestingModule or maybe FormsModule
    TestBed.configureTestingModule({
      imports: [ HttpClientTestingModule, FormsModule, RouterTestingModule.withRoutes([
            { path: 'profile', component: ProfileComponent }
        ])],
      declarations: [LoginComponent, ProfileComponent],
      providers: [{ provide: UserService, useValue: mockUserService }]
    })
    .compileComponents();
  }));


  beforeEach(() => {
    router = TestBed.get(Router); // remove the let here !!!!
    spyOn(router, 'navigate'); // spy on router navigate
    fixture = TestBed.createComponent(LoginComponent);
    component = fixture.componentInstance;
    debugElement = fixture.debugElement;
});

it('should go profile ', async(() => {
  fixture.detectChanges();
  mockUserService.login.and.returnValue(of({})); // mock login method on userService when it is called
  component.login();
  expect(router.navigate).toHaveBeenCalledWith(['/profile']);   
}));

it('should set error message on error ', async(() => {
  fixture.detectChanges();
  mockUserService.login.and.returnValue(throwError('Error')); // mock login method on userService when it is called
  component.login();
  expect(component.errorMessage).toBe('Username or password is incorrect.');
}));

});