如何使用mocha.js模拟依赖类进行单元测试?

49

假设我有两个 ES6 类。

这是 A 类:

import B from 'B';

class A {
    someFunction(){
        var dependency = new B();
        dependency.doSomething();
    }
}

并且类B:

class B{
    doSomething(){
        // does something
    }
}

我正在使用 mocha(带有 ES6 的 babel)、chai 和 sinon 进行单元测试,效果非常好。但是在测试类 A 时,如何为类 B 提供模拟类?

我想要模拟整个类 B(或所需的函数,实际上并不重要),以便类 A 不执行真正的代码,但我可以提供测试功能。

目前,mocha 测试的样子是这样的:

var A = require('path/to/A.js');

describe("Class A", () => {

    var InstanceOfA;

    beforeEach(() => {
        InstanceOfA = new A();
    });

    it('should call B', () => {
        InstanceOfA.someFunction();
        // How to test A.someFunction() without relying on B???
    });
});

了解关于 DI 的内容。 - Mritunjay
1个回答

49

你可以使用SinonJS创建一个stub来阻止真实函数的执行。

例如,给定类A:

import B from './b';

class A {
    someFunction(){
        var dependency = new B();
        return dependency.doSomething();
    }
}

export default A;

并且类B:

class B {
    doSomething(){
        return 'real';
    }
}

export default B;

测试可能看起来像这样:(sinon < v3.0.0

describe("Class A", () => {

    var InstanceOfA;

    beforeEach(() => {
        InstanceOfA = new A();
    });

    it('should call B', () => {
        sinon.stub(B.prototype, 'doSomething', () => 'mock');
        let res = InstanceOfA.someFunction();

        sinon.assert.calledOnce(B.prototype.doSomething);
        res.should.equal('mock');
    });
});

编辑:对于sinon版本>= v3.0.0,请使用以下内容:

describe("Class A", () => {

    var InstanceOfA;

    beforeEach(() => {
        InstanceOfA = new A();
    });

    it('should call B', () => {
        sinon.stub(B.prototype, 'doSomething').callsFake(() => 'mock');
        let res = InstanceOfA.someFunction();

        sinon.assert.calledOnce(B.prototype.doSomething);
        res.should.equal('mock');
    });
});

如果需要,您可以使用object.method.restore();来恢复函数:

var stub = sinon.stub(object, "method");
将object.method替换为一个存根函数。调用object.method.restore();(或stub.restore();)可以恢复原始函数。如果属性不是一个函数,则会抛出异常以帮助避免方法存根时的打字错误。


哇,太简单了。没想到要更改原型。谢谢! :) 你有没有关于如何模拟构造函数的提示?似乎不能以同样的方式工作? - mvmoay
1
请检查我几天前给出的答案:https://dev59.com/2FwY5IYBdhLWcg3wgX6V#32551410 - victorkt
你会如何为B的构造函数做这件事? - Willwsharp
1
ts-mock-imports 是我创造的一个库,它允许您模拟类导入,而不运行类构造函数。 - EmandM
这似乎已经被弃用了 https://github.com/sinonjs/sinon/issues/1761 正确的方法在这个文档中 https://sinonjs.org/releases/v5.0.3/stubs/ - nicoramirezdev
那个链接现在失效了,请使用这个链接:https://sinonjs.org/releases/latest/stubs/ - zumalifeguard

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接