Angular 11:HttpClient.get() 上单元测试间谍的错误类型检查

Angular 11: Wrong Typecheck for UnitTest Spy on HttpClient.get()

当单元测试 Angular 的 HttpClient.get(...) 函数时,似乎 TypeScript 在监视 HttpClient.get(...) 时无法正确检查类型响应类型。

升级到Angular11后出现这个错误。

beforeEach(async () => {
  await TestBed.configureTestingModule({
    imports: [HttpClientTestingModule],
    declarations: [AppComponent],
  }).compileComponents();
});

it('should check HttpClient.get()', () => {
  const http = TestBed.inject(HttpClient);
  const httpGetSpy = spyOn(http, 'get').and.returnValue(of('Test result.'));
  http.get('/test/url', { responseType: 'text' });
  
  expect(httpGetSpy).toHaveBeenCalledWith(
    '/test/url',
    { responseType: 'text'}
    // ^^^ Error:
    // "Type '"text"' is not assignable to type '"json" | undefined'.
  );
});

除了上面的简单复制器,这里还有一个更合理的示例,因为它出现在我的生产代码中:

// example.service.ts
@Injectable({ providedIn: 'root' })
export class ExampleService {
  constructor(private http: HttpClient) { }

  doSomething(): Observable<any> {
    return this.http.get('/some/url', { responseType: 'text' });
  }
}

// example.service.spec.ts
describe('ExampleService', () => {
  let service: ExampleService;

  beforeEach(() => {
    TestBed.configureTestingModule({
      imports: [HttpClientTestingModule]
    });
    service = TestBed.inject(ExampleService);
  });

  it('should be created', () => {
    const http = TestBed.inject(HttpClient);
    const httpGetSpy = spyOn(http, 'get').and.returnValue(of('Test result.'));
    service.doSomething().subscribe();
    expect(httpGetSpy).toHaveBeenCalledWith('/some/url', { responseType: 'text' });
  });
});

好的,所以您收到此错误的原因是因为 Angular 正朝着更强大的类型检查的方向发展。这将允许更好的构建优化。 Angular 11 修复了很多 'lose' 打字问题。您需要为您创建的间谍添加类型。

const httpGetSpy: jasmine.Spy<(arg0: string, {}) => Observable<string>> = spyOn(http, 'get').and.returnValue(of('Test result.'));

或者你可以简单地做这个

const httpGetSpy: jasmine.Spy<any> = spyOn(http, 'get').and.returnValue(of('Test result.'));