Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/428.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 每个测试实例的模拟依赖项类_Javascript_Asynchronous_Mocha.js_Sinon - Fatal编程技术网

Javascript 每个测试实例的模拟依赖项类

Javascript 每个测试实例的模拟依赖项类,javascript,asynchronous,mocha.js,sinon,Javascript,Asynchronous,Mocha.js,Sinon,我有一个模块,它实例化导入的类并异步调用这些实例的方法 考虑到我无法在测试结束时可靠地恢复模拟,我如何才能在每个测试用例中独立地模拟这些方法,从而使这些模拟仅在测试用例内部创建的情况下才有意义 例如: // tested class import B from './b'; import C from './c'; export default class A { someFunction() { let instanceB = new B(); return insta

我有一个模块,它实例化导入的类并异步调用这些实例的方法

考虑到我无法在测试结束时可靠地恢复模拟,我如何才能在每个测试用例中独立地模拟这些方法,从而使这些模拟仅在测试用例内部创建的情况下才有意义

例如:

// tested class 
import B from './b';
import C from './c';

export default class A {
  someFunction() {
    let instanceB = new B();
    return instanceB.doSomething()
      .then(() => this.doSomethingElse())
      .then((data) => {
        // async context, other tests will start before this.
        let instanceC = new C(data);
      });
  }
}

// test
import A from './a';
describe('test', () => {
  it('case1', () => {
    a = new A();
    // Mock B, C with config1
    return a.someFunction().then(() => {/* asserts1 */ });
  })
  it('case2', () => {
    a = new A();
    // Mock B, C with config2
    return a.someFunction().then(() => {/* asserts2 */ });
  })
})
如果我在case1中模拟B和C并同步恢复它们,C的配置将被覆盖,因为case2在异步上下文中在C实例化之前运行。 出于同样的原因,我无法在asserts1之后异步恢复模拟

也有类似的问题:, 但是它们并没有涵盖异步模拟的问题。

所以我最终使用了(不太好的)构造函数注入。如果您有更好的方法,包括可能完全不同的方法来测试和编写异步工厂,请分享,我很乐意接受

// tested class 
import B_Import from './b';
import C_Import from './c';

let B = B_Import;
let C = C_Import;
export function mock(B_Mock, C_Mock) {
    B = B_Mock || B_Import;
    C = C_Mock || C_Import;
}

export default class A {
  someFunction() {
    let instanceB = new B();
    return instanceB.doSomething()
      .then(() => this.doSomethingElse())
      .then((data) => {
        // async context, other tests will start before this.
        let instanceC = new C(data);
      });
  }
}


// test
import A, { mock as mockB } from './a';

setupMockB = (cfg, mockCallback) =>  {
    const ClassMock = class {
        constructor() {
            // use cfg
        }
        doSomething() {}
    } 
    if(mockCallback) {mockCallback(ClassMock.prototype);}
    mockB(ClassMock, null)
}

describe('test', () => {
  afterEach(() => mockB())
  it('case1', () => {
    a = new A();
    setupMockB(cfg1, (mb) => sinon.stub(mb, 'doSomething').resolves())
    return a.someFunction().then(() => { /* asserts1 */ });
  })
  it('case2', () => {
    a = new A();
    setupMockB(cfg2, (mb) => sinon.stub(mb, 'doSomething').rejects())
    return a.someFunction().then(() => { /* asserts2 */ });
  })
})