用玩笑嘲笑SerialPort

时间:2019-05-24 09:55:30

标签: javascript unit-testing jestjs node-serialport

我需要测试使用SerialPort的代码。 怎么开玩笑呢?我试图模拟SerialPort并更改write方法的实现:

protocol.js

import SerialPort from 'serialport'
const port = new SerialPort('/dev/ttyS0')

function getCRC(data) {
  let crc = 0
  for (let i = 0; i < data.length; i++) {
    crc ^= data[i]
    for (let j = 0; j < 8; j++) {
      if (crc & 0x0001) crc = 0x08408 ^ crc >> 1
      else crc >>>= 1
    }
  }
  return Array.of(crc & 0xFF, crc >> 8 & 0xFF)
}

function reset() {
  let msg = Array.of(0x02, 0x03, 0x06, 0x30)
  msg = msg.concat(getCRC(msg))
  port.write(msg)
}

export { reset }

protocol.spec.js

import { reset } from './protocol'
import SerialPort from 'serialport'

jest.mock('serialport')

describe('test protocol commands', () => {
  beforeAll(() => {
    SerialPort.mockImplementation(() => {
      return {
        write: () => {
          throw new Error('test error')
        }
      }
    })
  })

  it('should throw an error when calling reset command', () => {
    expect(() => reset()).toThrow()
  })
})

但是它不起作用。如何正确更改实现?

1 个答案:

答案 0 :(得分:0)

jest.mock呼叫被babel-jest挂起,因此该行首先运行:

jest.mock('serialport')

......会自动将serialport模块调出。

import行接下来运行,因此protocol.js被导入...并且在导入时,该行运行:

const port = new SerialPort('/dev/ttyS0')

...使用port的空自动模拟实现创建SerialPort

然后运行beforeAll,为SerialPort创建模拟实现,但这不会影响在port中创建的protocol.js,因为它已经创建了。 / p>


有几种方法可以修复它。

您可以延迟创建port,直到reset中需要它为止:

function reset() {
  let msg = Array.of(0x02, 0x03, 0x06, 0x30)
  msg = msg.concat(getCRC(msg))
  const port = new SerialPort('/dev/ttyS0')  // <= create port here
  port.write(msg)
}

您可以使用模块工厂函数来创建模拟:

import { reset } from './protocol'

jest.mock('serialport', () => {
  class MockSerialPort {
    write() {
      throw new Error('test error')
    }
  }
  return MockSerialPort;
});

describe('test protocol commands', () => {
  it('should throw an error when calling reset command', () => {
    expect(() => reset()).toThrow()  // Success!
  })
})

或者您可以在write的{​​{1}}上嘲笑prototype

SerialPort