Angular 单元测试因 NullInjector 错误而设置失败且未使用 Stub

问题描述 投票:0回答:1

我正在使用依赖于 HttpClient 的服务编写一个简单的独立注销组件测试。我尝试了不同的解决方案来存根 HttpAuthService ,到目前为止我尝试的每个解决方案都抛出:

NullInjectorError:R3InjectorError(独立[LogoutComponent])[HttpAuthService - > HttpAuthService - > HttpClient - > HttpClient]: NullInjectorError:没有 HttpClient 的提供者!

我尝试存根的服务:

@Injectable({
  providedIn: 'root'
})
export class HttpAuthService implements AuthService {

  private userSignal = signal<User|null>(null);
  private backendURL = environment.backendURL;

  public user = computed<User | null>(this.userSignal);
  constructor(private httpClient: HttpClient) {
  }
  login(params: { email: string; password: string }): Observable<void> {
    return this.httpClient.get<any[]>(`${this.backendURL}/users?email=${params.email}`)
      .pipe(
        tap(result=> {
          if (result.length > 0) {
            this.userSignal.set({userName: result[0].email})
          }
        }),
        map( result => {
          if (result.length == 0) {
            throw new Error('User not found');
          } else {
            return undefined;
          }
        })
      )
  }
  logout(): void {
    this.userSignal.set(null);
  }
}

注销组件:

@Component({
  selector: 'app-logout',
  standalone: true,
  imports: [MatButtonModule, MatIconModule],
  template: `
    <button mat-icon-button (click)="onLogout()" >
      <mat-icon>logout</mat-icon>
    </button>
  `,
  styles: ``
})
export class LogoutComponent {


  constructor(private authService: HttpAuthService) {
  }

  onLogout() {
    this.authService.logout();
  }
}

注销单元测试:

describe('LogoutComponent', () => {
  let component: LogoutComponent;
  let fixture: ComponentFixture<LogoutComponent>;
  const fakeAuthService = new AuthStub();

  beforeEach(async () => {
    await TestBed.configureTestingModule({
      imports: [LogoutComponent],
      providers: [{provide: HttpAuthService, useClass: AuthStub}]
    })
    .compileComponents();

    fixture = TestBed.createComponent(LogoutComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });

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

export  class AuthStub implements AuthService {
  login(params: { email: string; password: string }): Observable<void> {
    return of(undefined);
  }
  logout(): void {
  }
}

尝试过的解决方案:

  • 使用 jasmine.createSpyObj('', {//定义登录和注销}) 并使用 {provide/useValue} 添加到提供者
  • 按照下面的代码使用 AuthStub,创建一个带有新实例的 const,并使用 {provide/useValue} 添加到提供者
  • 按照下面的代码使用 AuthStub,创建一个带有新实例的 const,并使用 {provide/useClass} 添加到提供者

为了排除 IDE (Webstorm),我还在终端中使用 ng test 运行了测试。测试设置使用默认的 ng Karma/jasmine 测试设置和 Playwright 进行 e2e 测试。

angular unit-testing jasmine karma-runner angular-standalone-components
1个回答
0
投票

你能尝试一下这个代码吗,我认为由于它是独立的组件,所以需要以不同的方式实例化!

describe('LogoutComponent', () => {
  let component: LogoutComponent;
  let fixture: ComponentFixture<LogoutComponent>;

  beforeEach(async () => {
    fixture = await render(LogoutComponent, {
      providers: [
        {
          provide: HttpAuthService,
          useValue: {
            logout: () => { }
          }
        }
      ]
    });
    component = fixture.componentInstance;
    fixture.detectChanges();
  });

  it('should create', () => {
    expect(component).toBeTruthy();
  });
});
© www.soinside.com 2019 - 2024. All rights reserved.