【问题标题】:Mock SerialPort with jest用玩笑模拟 SerialPort
【发布时间】:2019-05-25 11:00:31
【问题描述】:

我需要测试使用 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()
  })
})

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

【问题讨论】:

    标签: javascript unit-testing jestjs node-serialport


    【解决方案1】:

    jest.mock 调用被babel-jest 提升,所以这条线首先运行:

    jest.mock('serialport')
    

    ...自动模拟 serialport 模块。

    import 行接下来运行,因此 protocol.js 被导入...当它被导入时,此行运行:

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

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

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


    有几种方法可以解决它。

    您可以延迟创建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!
      })
    })
    

    或者您可以在SerialPortprototype 上模拟write

    import { reset } from './protocol'
    import SerialPort from 'serialport'
    
    jest.mock('serialport')
    
    describe('test protocol commands', () => {
      beforeAll(() => {
        const mock = jest.spyOn(SerialPort.prototype, 'write');
        mock.mockImplementation(() => {
          throw new Error('test error')
        });
      })
    
      it('should throw an error when calling reset command', () => {
        expect(() => reset()).toThrow()  // Success!
      })
    })
    

    【讨论】:

      猜你喜欢
      • 2019-04-24
      • 1970-01-01
      • 1970-01-01
      • 2021-01-06
      • 2020-02-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-10-06
      相关资源
      最近更新 更多