在打字稿中使用笑话模拟请求模块功能

时间:2019-05-06 12:18:36

标签: node.js typescript jestjs

我正在尝试在打字稿中使用request()来模拟节点模块request的{​​{1}}函数,但是我无法做到这一点,有人可以帮助我哪里出了问题吗?顺便说一句,我试图创建一个通用代理函数,该函数应与所有http方法(例如get,post,delete,update)一起使用。所以我只想使用jest函数,而不是使用基于请求方法的if-else梯形图来代替request.get(),request.post()... etc。

Proxy.ts:

request()

Proxy.spec.ts:

import * as request from 'request';

export default class ProxyClass {
  static proxy(req: any, res: any): any {
    const options: any = {
      headers: req.headers,
    }
    const proxyReq: any = request(options);
    proxyReq.on('error', (err: any) => {
      return res.status(500).send(err);
    });
    return proxyReq.pipe(res);
  }
}

当我通过测试时,我得到了错误: import 'jest'; import * as request from 'request'; import {Request} from 'jest-express/lib/request'; import {Response} from 'jest-express/lib/response'; import ProxyClass from './Proxy'; describe('proxy request', () => { const req: any = new Request(); const res: any = new Response(); it('should call pipe', () => { const mockRequest = { pipe: jest.fn(), on: jest.fn(), } jest.mock('request', () => { return function() { return mockRequest; } }); ProxyClass.proxy(req, res); expect(mockRequest.pipe).toHaveBeenCalledTimes(1); jest.clearAllMocks(); }); });

1 个答案:

答案 0 :(得分:1)

如果您获得TypeError: request is not a function,则可能是在TypeScript配置中将esModuleInterop设置为true

在这种情况下,您需要像这样导入request

import request from 'request';

TypeScript和ES6模块与旧模块样式不同,esModuleInterop标志告诉TypeScript做一些额外的工作来编译旧模块的import语句,使其像新样式一样工作。 ..在这种情况下,将单个函数导出视为TypeScript / ES6模块的default导出。


jest.mock doesn't work inside a test,因此您需要将其移至测试之外。

如果您将工厂函数作为第二个参数传递,则它必须是完全独立的,因为对jest.mock的调用会被吊起,并且将在测试文件中的其他任何函数之前运行。

在这种情况下,您可以使模拟对象每次都返回相同的对象,这样您就可以在测试期间获取模拟对象并检查其是否按预期被调用:

import request from 'request';
import {Request} from 'jest-express/lib/request';
import {Response} from 'jest-express/lib/response';
import ProxyClass from './Proxy';

jest.mock('request', () => {
  const mockRequest = {
    pipe: jest.fn(),
    on: jest.fn(),
  }
  return function() {
    return mockRequest;  // <= returns the same object every time...
  }
});

describe('proxy request', () => {
  const req: any = new Request();
  const res: any = new Response();
  it('should call pipe', () => {
    const mockRequest = request();  // <= ...so you can get it here
    ProxyClass.proxy(req, res);
    expect(mockRequest.pipe).toHaveBeenCalledTimes(1);  // Success!
    jest.clearAllMocks();
  });
});

(请注意,您不需要导入jest,因为jest会加载并运行您的测试文件,并且已经将其自身插入了全局范围)