【问题标题】:Unit Testing Controllers use Jest, NodeJS单元测试控制器使用 Jest、NodeJS
【发布时间】:2025-12-15 22:00:01
【问题描述】:

我想检查某些路由调用正确控制器的情况,使用 Jest 特定 (模拟或间谍)

这是针对单元测试的特定情况。有人可以帮助我如何使用玩笑来检查它。我不需要验证类型 期望(状态代码或 res 对象)我需要检查是否已调用 controller。 谢谢!

例如:

// todoController.js
function todoController (req, res) {
    res.send('Hello i am todo controller')
} 

// index.spec.js
const express = require('express');
const request = require('request-promise');
const todoController = require('./todoController');
jest.mock('./todoController');

const app = express();

app.get('/todo', todoController)

test('If certain routes are calling the correct controller , controller should to have been called times one.', async() => {
    await request({url: 'http://127.0.0.1/todo'})
    expect(todoController).toHaveBeenCalledTimes(1);
})

【问题讨论】:

    标签: javascript node.js unit-testing express jestjs


    【解决方案1】:

    实际上,如果您搜索,那里有很多参考资料。

    下面,我分享一些我知道的方法。

    使用模拟请求/响应测试 Express 应用程序的一大概念飞跃是了解如何模拟链式

    API 例如。 res.status(200).json({ foo: 'bar' }).

    首先你可以制作某种拦截器,这是通过从它的每个方法中返回 res 实例来实现的:

    // util/interceptor.js
    module.exports = {
      mockRequest: () => {
        const req = {}
        req.body = jest.fn().mockReturnValue(req)
        req.params = jest.fn().mockReturnValue(req)
        return req
      },
    
      mockResponse: () => {
        const res = {}
        res.send = jest.fn().mockReturnValue(res)
        res.status = jest.fn().mockReturnValue(res)
        res.json = jest.fn().mockReturnValue(res)
        return res
      },
      // mockNext: () => jest.fn()
    }
    

    Express 用户级 API 基于中间件。一个接受请求(通常称为 req)、响应(通常称为 res)和下一个(调用下一个中间件)作为参数的中间件。

    然后你有这样的控制器:

    // todoController.js
    function todoController (req, res) {
        if (!req.params.id) {
          return res.status(404).json({ message: 'Not Found' });
        }
    
        res.send('Hello i am todo controller')
    }
    

    它们通过“挂载”在 Express 应用程序 (app) 实例(在 app.js 中)上来使用:

    // app.js
    const express = require('express');
    const app = express();
    
    const todoController = require('./todoController');
    
    app.get('/todo', todoController);
    

    使用我们之前定义的 mockRequest 和 mockResponse,然后我们会假设 res.send() 是使用正确的负载 ({ data }) 调用的。

    所以在你的测试文件上:

    // todo.spec.js
    const { mockRequest, mockResponse } = require('util/interceptor')
    const controller = require('todoController.js')
    
    describe("Check method \'todoController\' ", () => {
      test('should 200 and return correct value', async () => {
        let req = mockRequest();
        req.params.id = 1;
        const res = mockResponse();
    
        await controller.todoController(req, res);
    
        expect(res.send).toHaveBeenCalledTimes(1)
        expect(res.send.mock.calls.length).toBe(1);
        expect(res.send).toHaveBeenCalledWith('Hello i am todo controller');
      });
    
      test('should 404 and return correct value', async () => {
        let req = mockRequest();
        req.params.id = null;
        const res = mockResponse();
    
        await controller.todoController(req, res);
    
        expect(res.status).toHaveBeenCalledWith(404);
        expect(res.json).toHaveBeenCalledWith({ message: 'Not Found' });
      });
    });
    

    这只是测试 Express 处理程序和中间件的一种方法。另一种方法是启动 Express 服务器。

    【讨论】: