Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/455.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 在Jest中模拟外部类依赖关系_Javascript_Unit Testing_Mocking_Jestjs - Fatal编程技术网

Javascript 在Jest中模拟外部类依赖关系

Javascript 在Jest中模拟外部类依赖关系,javascript,unit-testing,mocking,jestjs,Javascript,Unit Testing,Mocking,Jestjs,我真的很挣扎,所以请任何形式的帮助是非常感谢 我有一个导出类的ExternalDependency模块 TestSubject是另一个类模块。 当TestSubject将被实例化时,一个ExternalDependency实例将在此内部合成 出于测试目的,我想有选择地在ExternalDependency类的模拟版本和真实版本之间交换 ExternalDependency.js module.exports = class ExternalDependency { constructor (

我真的很挣扎,所以请任何形式的帮助是非常感谢

我有一个导出类的ExternalDependency模块

TestSubject是另一个类模块。
当TestSubject将被实例化时,一个ExternalDependency实例将在此内部合成

出于测试目的,我想有选择地在ExternalDependency类的模拟版本和真实版本之间交换

ExternalDependency.js

module.exports = class ExternalDependency {
  constructor () {
    this.isMocked = false
  }
}
TestSubject.js

const ExternalDependency = require('./ExternalDependency')

module.exports = class TestSubject {
  constructor () {
    this.externalDependency = new ExternalDependency()
  }

  isExternalDependencyMocked () {
    return this.externalDependency.isMocked
  }
}
Test.js

const TestSubject = require('./TestSubject')

const MockedExternalDependency = class ExternalDependency {
  constructor () {
    this.isMocked = true
  }
}

describe ('TestSubject', () => {
  it ('will require and instantiate the real ExternalDependency', () => {
    const testSubject = new TestSubject()
    expect(testSubject.isExternalDependencyMocked()).toEqual(false)
  })
  it ('or the mocked one here', () => {
    jest.mock('./ExternalDependency', MockedExternalDependency) 
        // Failing with: 
        // babel-plugin-jest-hoist: The second argument
        // of `jest.mock` must be a function.
    const testSubject = new TestSubject()
    expect(testSubject.isExternalDependencyMocked()).toEqual(true)
  })
  it ('and back to the real', () => {
    jest.unmock('./ExternalDependency')
    const testSubject = new TestSubject()
    expect(testSubject.isExternalDependencyMocked()).toEqual(false)
  })
})
好的,我知道这是错的。

但是,我怎样才能达到类似的行为呢?

对于任何一个正在为此奋斗的人来说…
刚刚醒来,发现了可能的解决办法

所以,首先让我们试着理解笑话是如何运作的:

// __mock__/ExternalDependency.js
module.exports = 'MOCK'

// ExternalDependency.js
module.exports = 'REAL'

// TestSubject.js
module.exports = require('./ExternalDependency')

// TestSubject.spec.js
const TestSubject = require('./TestSubject')

describe ('TestSubject', () => {
  it ('will require the real ExternalDependency', () => {
    expect(TestSubject).toEqual('REAL')
  })
  it ('or the mocked one here', () => {
    jest.resetModules()
    jest.mock('./ExternalDependency')
    // This will work just fine:
    // jest.mock('./ExternalDependency', () => {return 'MOCK'})
    const TestSubjectMocked = require('./TestSubject')
    expect(TestSubjectMocked).toEqual('MOCK')
  })
  it ('and back to the real', () => {
    expect(TestSubject).toEqual('REAL')
  })
})
然后解决方案应该很简单:

// __mock__/ExternalDependency.js
module.exports = class ExternalDependency {
  constructor () {
    this.isMocked = true
  }
}

// ExternalDependency.js
module.exports = class ExternalDependency {
  constructor () {
    this.isMocked = false
  }
}

// TestSubject.js
const ExternalDependency = require('./ExternalDependency')

module.exports = class TestSubject {
  constructor () {
    this.externalDependency = new ExternalDependency()
  }

  isExternalDependencyMocked () {
    return this.externalDependency.isMocked
  }
}

// TestSubject.spec.js
const TestSubject = require('./TestSubject')

const mock = () => {
  return class ExternalDependency {
    constructor () {
      this.isMocked = true
    }
  }
}

describe ('TestSubject', () => {
  it ('will require and instantiate the real ExternalDependency', () => {
    const testSubject = new TestSubject()
    expect(testSubject.isExternalDependencyMocked()).toEqual(false)
  })
  it ('or the mocked one here', () => {
    jest.resetModules()
    jest.mock('./ExternalDependency')
    // This works fine too:
    // jest.doMock('./ExternalDependency', mock) // you really need doMock here!
    const TestSubjectMocked = require('./TestSubject')
    const testSubject = new TestSubjectMocked()
    expect(testSubject.isExternalDependencyMocked()).toEqual(true)
  })
  it ('and back to the real', () => {
    const testSubject = new TestSubject()
    expect(testSubject.isExternalDependencyMocked()).toEqual(false)
  })
})
也可以插入类声明:

// TestSubject.js
const ExternalDependency = require('./ExternalDependency')

module.exports = class TestSubject {
  constructor () {
    this.externalDependency = new ExternalDependency()
  }

  isExternalDependencyMocked () {
    return this.externalDependency.isMocked
  }

  isSpied() {
    this.externalDependency.isSpied()
  }
}

// TestSubject.spec.js
const spy = jest.fn()
const mock = (value) => {
  return () => {
    return class ExternalDependency {
      constructor () {
        this.isMocked = value
      }
      isSpied () {
        spy()
      }
    }
  }

}
jest.resetModules()
jest.doMock('./ExternalDependency', mock('MyMock'))
const ExternalDependencyMocked = require('./ExternalDependency')
const TestSubjectMocked = require('./TestSubject')

describe ('TestSubject', () => {
  it ('tested injected', () => {
    const testSubject = new TestSubjectMocked()
    expect(testSubject.isExternalDependencyMocked()).toEqual('MyMock')
    testSubject.isSpied()
    expect(spy).toHaveBeenCalled()
  })
})