单元测试依赖注入

Unit testing dependency injections

我想在 class 中模拟依赖关系,但我找不到正确的方法来实现它。使用 sinon 进行单元测试。例如:

const { classB } = require("./classes/classB");
const { classC } = require("./classes/classC");
const sinon = require("sinon");

class classA {
    constructor() {
        this.classB = new classB();
        this.classC = new classC();
    }
 
    doSomething() {
        const data = this.classB.getInfo();
        const processed = processInfo(data);
        this.classC.processedData(processed);
        
    }
    
    processInfo(data) {
        // doesSomeProcessing
    }
}

module.exports = {
    classA
};

describe("classA", () => {
    describe("when instantiated", () => {
        it("calls classB's getInfo once, classC's processedData data once.", () => {
            sinon.stub(classB);
            let clsA = new classA();
            sinon.assert.calledOnce(classB.getInfo);
            sinon.assert.calledOnce(classC.processedData);
            // Also can we do something like this?
            // when classB.getinfo.then(provideMockData) 
            // so that we can mock the calls being made to avoid actual calls?
        });
    });
});

我尝试对此进行研究,但找不到可行的解决方案。任何见解都会非常有帮助!提前致谢,对于造成的任何麻烦,我们深表歉意!

你应该用 Link Seams.

消除依赖

例如

classA.js:

const { ClassB } = require('./classB');
const { ClassC } = require('./classC');

class ClassA {
  constructor() {
    this.classB = new ClassB();
    this.classC = new ClassC();
  }

  doSomething() {
    const data = this.classB.getInfo();
    this.classC.processedData(data);
  }
}

module.exports = { ClassA };

classB.js:

class ClassB {
  getInfo() {
    return 'real data';
  }
}

module.exports = { ClassB };

classC.js:

class ClassC {
  processedData(data) {
    return 'real process data';
  }
}

module.exports = { ClassC };

classA.test.js:

const sinon = require('sinon');
const proxyquire = require('proxyquire');

describe('66751571', () => {
  it('should pass', () => {
    const classBInstanceStub = {
      getInfo: sinon.stub().returns('teresa teng'),
    };
    const classCInstanceStub = {
      processedData: sinon.stub(),
    };
    const ClassBStub = sinon.stub().returns(classBInstanceStub);
    const ClassCStub = sinon.stub().returns(classCInstanceStub);
    const { ClassA } = proxyquire('./classA', {
      './classB': { ClassB: ClassBStub },
      './classC': { ClassC: ClassCStub },
    });
    const clsA = new ClassA();
    clsA.doSomething();
    sinon.assert.calledOnce(classBInstanceStub.getInfo);
    sinon.assert.calledWithExactly(classCInstanceStub.processedData, 'teresa teng');
  });
});

单元测试结果:

  66751571
    ✓ should pass (2326ms)


  1 passing (2s)

-----------|---------|----------|---------|---------|-------------------
File       | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
-----------|---------|----------|---------|---------|-------------------
All files  |   81.82 |      100 |      50 |   81.82 |                   
 classA.js |     100 |      100 |     100 |     100 |                   
 classB.js |      50 |      100 |       0 |      50 | 3                 
 classC.js |      50 |      100 |       0 |      50 | 3                 
-----------|---------|----------|---------|---------|-------------------