在 Typescript 中使用 Jest + Supertest 进行模拟

Posted

技术标签:

【中文标题】在 Typescript 中使用 Jest + Supertest 进行模拟【英文标题】:Mocking with Jest + Supertest in Typescript 【发布时间】:2021-01-13 19:25:42 【问题描述】:

我正在使用 typescript 中的 jest 编写一个模拟测试用例,并尝试使用 supertest 模拟 API 调用,但无法获得模拟响应作为回报,因为我在登录功能上使用 Axios,甚至尝试模拟 Axios打电话但没有运气。

这是我的代码:

auth.controller.ts

import  AxiosService  from "helpers";

export class AuthController 
    constructor() 
       ...
      // Some logic is written here
      this.init()
    

    public init() 
       // prepared an route for login
       router.post('/api/auth/login', this.login);
    
  
    login = async function (req: Request, res: Response): Promise<void> 
        // Preparing config for axios call with some logic
        ...

        // created a service for Axios call to some third party.
        AxiosService.call(req, res, config, "login");
    
  
    
    

auth.test.ts

import  AuthController  from "../../modules/auth/auth.controller";
jest.mock("../../modules/auth/auth.controller");

beforeAll(async () => 
  const auth = new AuthController();
  mockLogin = jest.spyOn(auth, "login");
);

afterAll(async () => 
  server.stop();
);

test("should give login response", async () => 
    mockLogin.mockImplementation(() => 
      return Promise.resolve( Success: true, body: "Login" );
    );

      const response = await request(server.app)
        .post("/api/auth/login")
        .send(requestBody)
        .expect(200);

      response.body // Getting the server response instead of mocked one
)
    
    

也尝试使用此代码,但那里没有运气:

jest.mock('../../modules/auth/auth.controller', () => 
  return  
    AuthController: jest.fn().mockImplementation(() => 
          return 
              login: jest.fn()
             
      )
  
)
            
    

这是我的 AxiosService 类的样子:

export class AxiosService 

  public static async call(...):Promise<void>  
    try  
       const  data  = await axios(...);

       res.status(200).json(data);
     catch(err) 
       res.status(400).send(err);
     
  
  

尝试使用以下行模拟 AxiosService 调用方法:

jest.mock('../../helpers/AxiosService', () => 
  return jest.fn().mockImplementation(() => 
    return  call: () =>  return success:true, data:'mock' 
  )
)

但是,在模拟 Axios 调用之后,我得到 在 jest.setTimeout 指定的 10000(我已经给出)毫秒超时内没有调用异步回调

任何人都可以提供帮助,这对我来说非常有用,因为我是模拟概念的新手,所以也许我在这里遗漏了一些东西。

提前致谢

【问题讨论】:

模拟 AuthController 没有意义,因为它是您测试的单元。模拟 AxiosService 等其他单元。 @EstusFlask,感谢您的回复,我已经尝试过了,但它没有按预期工作。 什么不起作用?无论如何,这就是它需要完成的方式,问题应该是关于该尝试而不是模拟 AuthController 进行自己的测试。 @EstusFlask,我通过 jest.mock(...) 模拟了 AxiosService 的调用函数,但它没有给出任何响应,而是通过给出“未在内部调用异步回调”来完成操作jest.setTimeout 指定的 10000(我给出的)毫秒超时”。实际上,我对这个概念也有点陌生,也许我在这里遗漏了一些东西。 请提供可以重现问题的***.com/help/mcve。不知道这是怎么回事。 【参考方案1】:

一个适当的测试策略,除了测试一个单元之外的每个单元都需要被模拟。

由于 Supertest 等待服务器响应而发生超时,并且在模拟 AxiosService 的情况下没有,因此需要模拟如下:

...
return  call: (req, res) =>  res.status(200).json(success:true, data:'mock'); 

在这种情况下,测试可以使用模拟的服务类模拟控制器类,或者与模拟的 Axios 一起测试它们。由于 AuthController 不单独做很多事情(AuthController 和 AxiosService 是对简单 Express 处理程序的抽象),它可以是:

jest.mock('axios', () => jest.fn()) // at top level
...
axios.mockResolvedValue( data: ... );
const response = await request(server.app)

【讨论】:

以上是关于在 Typescript 中使用 Jest + Supertest 进行模拟的主要内容,如果未能解决你的问题,请参考以下文章

在 Typescript 中使用 Jest + Supertest 进行模拟

在 TypeScript 中使用 NextJS 设置 Jest + React 测试库 -- 设置 upp jest.config.js 时出错

如何在 TypeScript 中使用 Jest 和 Knex 进行测试?

如何在 Jest 的自定义测试环境文件中使用 TypeScript?

使用 Typescript 从 Jest 手动模拟中导入函数

Vue Typescript 组件 Jest 测试不会在 html 中呈现值