【问题标题】:expressJS/jestJS: How to split get() function to write simple jest unit test?expressJS/jestJS:如何拆分 get() 函数来编写简单的 jest 单元测试?
【发布时间】:2019-03-21 09:46:16
【问题描述】:

如何在 expressJS 应用程序中定义 get() 路由以进行简单的单元测试?

所以作为第一步,我将get() 的函数移到了一个自己的文件中:

index.js

const express = require('express')
const socketIo = require('socket.io')
const Gpio = require('pigpio').Gpio

const app = express()
const server = http.createServer(app)
const io = socketIo(server)

const setStatus = require('./lib/setStatus.js')

app.locals['target1'] = new Gpio(1, { mode: Gpio.OUTPUT })

app.get('/set-status', setStatus(app, io))

lib/setStatus.js

const getStatus = require('./getStatus.js')

module.exports = (app, io) => {
  return (req, res) => {
    const { id, value } = req.query // id is in this example '1'
    req.app.locals['target' + id].pwmWrite(value))
    getStatus(app, io)
    res.send({ value }) // don't need this
  }
}

lib/getStatus.js

const pins = require('../config.js').pins

module.exports = async (app, socket) => {
  const res = []
  pins.map((p, index) => {
    res.push(app.locals['target' + (index + 1)].getPwmDutyCycle())
  })
  socket.emit('gpioStatus', res)
}

所以首先我不太确定,如果我正确拆分代码 - 考虑进行单元测试。

对我来说,调用/set-status?id=1&value=50 唯一要做的就是调用pwmWrite() 获取一个(我猜的)对象,该对象由new Gpio 定义并存储在expressJS 的locals 中。

第二个:如果这应该是正确的方法,我不明白如何编写一个 jestJS 单元测试来检查 pwmWrite 是否已被调用 - 这是一个异步函数内部。

这是我的尝试,但我无法测试 pwmWrite 的内部调用:

test('should call pwmWrite() and getStatus()', async () => {
  const app = {}
  const io = { emit: jest.fn() }
  const req = {
    app: {
      locals: {
        target1: { pwmWrite: jest.fn() }
        }
      }
    }
  }
  expect.assertions(1)
  expect(req.app.locals.target1.pwmWrite).toHaveBeenCalled()
  await expect(getStatus(app, io)).toHaveBeenCalled()
})

【问题讨论】:

  • 好吧,app.locals['target1'].pwmWrite = jest.fn() ?
  • 代码库似乎没问题,不清楚您的测试在哪里实际调用setStatus

标签: javascript unit-testing express jestjs


【解决方案1】:

你们很亲密,只是缺少了一些东西。

你需要在expect语句之前调用setStatusgetStatus方法, 并且您在 req.queryres 上缺少模拟,因为 getStatus 使用它们。

test('should call pwmWrite() and getStatus()', async () => {
  const app = {}
  const io = {};
  const req = {
    query: {
      id: '1',
      name: 'foo'
    },
    app: {
      locals: {
          target1: { pwmWrite: jest.fn() }
      }
    }
  };
  const res = { send: jest.fn() };

  // Mock getStatus BEFORE requiring setStatus
  jest.mock('./getStatus');

  //OBS Use your correct module paths
  const setStatus = require('./setStatus');
  const getStatus = require('./getStatus');


  // Call methods
  setStatus(app, io)(req, res);

  expect.assertions(2);

  // Get called in setStatus
  expect(req.app.locals.target1.pwmWrite).toHaveBeenCalled();

  // See if mocked getStatus has been called
  await expect(getStatus).toHaveBeenCalled();
});

getStatus 需要在需要 setStatus 之前进行模拟,因为它在那里使用过

【讨论】:

  • 我正在考虑模拟getStatus(),因为我只想调用setStatus 并测试是否调用了getStatus。我不想测试发出事件。
  • 您能否在@user3142695 上面的问题中包含getStatus 方法?
  • 如果在问题中添加了代码。但这部分由自己的测试处理。当我尝试进行单元测试时,我正在单独对其进行测试。所以setStatus 根本不应该进入getStatus,而应该只测试expect(getStatus).toHaveBeenCalled() - 无论发生什么。
  • @user3142695,我想我明白了!
  • 为什么我必须先调用模拟?
猜你喜欢
  • 1970-01-01
  • 2016-03-10
  • 1970-01-01
  • 1970-01-01
  • 2021-04-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多