用 Jest 测试 TypeScript:"no overload matches this call"

Testing TypeScript with Jest: "no overload matches this call"

我正在使用 Jest 测试 Apollo 服务器 RESTDataSource。我的应用程序是用 TypeScript 编写的。我的 class、CDCDataSource 扩展了摘要 class RESTDataSource,它本身扩展了摘要 class DataSourceRESTDataSource 的方法 get 允许您从外部 REST 数据源中提取数据。我希望模拟的正是这种方法,因为我希望模拟外部数据源。

  protected async get<TResult = any>(
    path: string,
    params?: URLSearchParamsInit,
    init?: RequestInit,
  ): Promise<TResult> {
    return this.fetch<TResult>(
      Object.assign({ method: 'GET', path, params }, init),
    );
  }

但是,当我尝试使用 Jest 的 spyOn 模拟此方法时——按照此处的第二个答案:——

import CDCDataSource from '../CDCDataSource';

test('Test', () => {
    let dataSource = new CDCDataSource();
    let spy = jest.spyOn(dataSource, 'get').mockImplementation(() => 'Hello');
    expect(dataSource.get()).toBe('Hello');


但是,我收到 TypeScript 错误

TS2768: No overload matches this call

jest.spyOn(dataSource,'get')

中的 get

然后我得到

超过

中的 get

expect(dataSource.get()).toBe('Hello');

所以问题的一部分似乎是这是一个保护方法——我不清楚如何测试这个方法以便能够模拟 API。

我的 tsconfig.json

{
  "compilerOptions": {
    "target": "ES6",
    "lib": [
      "esnext",
      "dom"
    ],
    "skipLibCheck": true,
    "outDir": "dist",
    "strict": false,
    "forceConsistentCasingInFileNames": true,
    "esModuleInterop": true,
    "module": "commonjs",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "sourceMap": true,
    "alwaysStrict": true,
  },
  "exclude": [
    "node_modules"
  ]
}

这是一个 Node Apollo Server 项目(使用 Node 12.14.0 和 TypeScript 3.8.3)

感谢您提供任何线索!

您正在尝试访问 protected 方法。

如果您不想或不能重新构建您的 class,您可以使用 ts-ignore 来抑制错误。

    // @ts-ignore`
    let spy = jest.spyOn(dataSource, 'get').mockImplementation(() => 'Hello');

或者您可以扩展原始的 class,使用仅用于测试的 class,它将有一个 public 方法,该方法将仅代理到受保护的方法。

test('Protected method',()=>{

  class Test extends OriginalClass {
    testProtected(){
      super.protectedMethod()
    }
  }
  let dataSource = new Test();
  let spy = jest.spyOn(dataSource, 'testProtected').mockImplementation(() => 'Hello');
})