Vue.js单元测试如何使用Sinon存根伪造audioContext?

时间:2017-10-02 10:57:51

标签: unit-testing vue.js sinon-chai

我正在尝试测试一个音频插件,但我不知道如何写出正确的期望:

audioContex.resume()
audioContext.suspend()

测试正确执行,更新指令(Vue.noise)并执行命令Vue.noise.start() 但期望是失败的

expect(audioContext).to.be.calledWith('resume')

使用以下控制台输出

1) should start white noise
     VueNoiseGeneratorPlugin
     TypeError: {} is not a spy or a call to a spy!
    at assertCanWorkWith (/Developments/pomodoros/pomodoro/node_modules/sinon-chai/lib/sinon-chai.js:53:19)
    at Assertion.<anonymous> (/Developments/pomodoros/pomodoro/node_modules/sinon-chai/lib/sinon-chai.js:98:13)
    at Assertion.ctx.(anonymous function) [as calledWith] (/Developments//pomodoros/pomodoro/node_modules/chai/chai.js:4192:25)
    at Context.<anonymous> (webpack:///test/unit/specs/plugins/VueNoiseGeneratorPlugin.spec.js:39:31 <- index.js:24935:32)

这是插件

VueNoiseGeneratorPlugin.js

import _ from 'underscore'

// Thanks to this great tutorial: http://noisehack.com/generate-noise-web-audio-api/
var audioContext, bufferSize, noise
audioContext = new (window.AudioContext || window.webkitAudioContext)()

function generateWhiteNoise () {
  var noiseBuffer, output

  bufferSize = 2 * audioContext.sampleRate
  noiseBuffer = audioContext.createBuffer(1, bufferSize, audioContext.sampleRate)

  output = noiseBuffer.getChannelData(0)
  _.times(bufferSize, i => {
    output[i] = Math.random() * 2 - 1
  })

  noise = audioContext.createBufferSource()
  noise.buffer = noiseBuffer
  noise.loop = true
  noise.start(0)

  return noise
}

function generatePinkNoise () {
  bufferSize = 4096
  noise = (function () {
    var b0, b1, b2, b3, b4, b5, b6, node
    b0 = b1 = b2 = b3 = b4 = b5 = b6 = 0.0
    node = audioContext.createScriptProcessor(bufferSize, 1, 1)
    node.onaudioprocess = function (e) {
      var output

      output = e.outputBuffer.getChannelData(0)
      _.times(bufferSize, i => {
        var white = Math.random() * 2 - 1
        b0 = 0.99886 * b0 + white * 0.0555179
        b1 = 0.99332 * b1 + white * 0.0750759
        b2 = 0.96900 * b2 + white * 0.1538520
        b3 = 0.86650 * b3 + white * 0.3104856
        b4 = 0.55000 * b4 + white * 0.5329522
        b5 = -0.7616 * b5 - white * 0.0168980
        output[i] = b0 + b1 + b2 + b3 + b4 + b5 + b6 + white * 0.5362
        output[i] *= 0.11 // (roughly) compensate for gain
        b6 = white * 0.115926
      })
    }
    return node
  })()

  return noise
}

function generateBrownNoise () {
  bufferSize = 4096

  noise = (function () {
    var lastOut, node

    lastOut = 0.0
    node = audioContext.createScriptProcessor(bufferSize, 1, 1)
    node.onaudioprocess = function (e) {
      var output = e.outputBuffer.getChannelData(0)
      _.times(bufferSize, i => {
        var white = Math.random() * 2 - 1
        output[i] = (lastOut + (0.02 * white)) / 1.02
        lastOut = output[i]
        output[i] *= 3.5 // (roughly) compensate for gain
      })
    }
    return node
  })()

  return noise
}

export default {
  install: function (Vue) {
    console.log('installing VueNoisGenerator plugin')
    Vue.directive('noise', (value) => {
      var noise

      switch (value) {
        case 'white':
          noise = generateWhiteNoise()
          break
        case 'pink':
          noise = generatePinkNoise()
          break
        case 'brown':
          noise = generateBrownNoise()
          break
        default:
          noise = generateWhiteNoise()
      }
      noise.connect(audioContext.destination)
      audioContext.suspend()
    })
    Vue.noise = {
      start () {
        console.log('method start called')
        audioContext.resume()
      },
      pause () {
        console.log('method pause called')
        audioContext.suspend()
      },
      stop () {
        console.log('method stop called')
        audioContext.suspend()
      }
    }
  }
}

这是我的spec.js

VueNoiseGeneratorPlugin.spec.js

import Vue from 'vue'
import App from '@/App'
import VueNoiseGeneratorPlugin from '@/plugins/VueNoiseGeneratorPlugin'

import sinon from 'sinon'
import { mount } from 'avoriaz'

Vue.use(VueNoiseGeneratorPlugin)

Vue.filter('addspace', (value) => {
  return value + ' '
})

Vue.filter('uppercase', (key) => {
  return key.toUpperCase()
})

Vue.filter('leftpad', (value) => {
  if (value >= 10) {
    return value
  }
  return '0' + value
})

describe('VueNoiseGeneratorPlugin', () => {
  let wrapper
  // let audioContext = new (window.AudioContext || window.webkitAudioContext)()

  let audioContext = {}
  sinon.stub(audioContext, 'resume').returns('OK')

  beforeEach(() => {
    wrapper = mount(App)
  })

  it('should start white noise', () => {
    wrapper.vm.noise = 'white'
    Vue.noise.start()
    expect(audioContext).to.be.calledWith('resume')
  })
})

1 个答案:

答案 0 :(得分:0)

由于audioContext存在一些副作用,我不应该使用存根,而是使用存根。模拟

   let audioContext = sinon.mock(new (window.AudioContext || window.webkitAudioContext)())

然后

  it('should start white noise', () => {
    wrapper.vm.noise = 'white'
    Vue.noise.start()
    audioContext.expects('resume').once()
  })