嘲笑 os.type() 不起作用

Mockery mocking os.type() is not working

我正在尝试对我的一个模块进行单元测试,该模块依赖于底层 OS。

我正在尝试根据不同的测试装置使用模拟来模拟 os.type() 到 return Linux/Windows_NT。

我使用 mocha 作为我的单元测试框架。

我有一个描述部分,它对我的​​模块的功能 A 进行单元测试,其中有 2 个描述块:一个用于 Windows,一个用于 Linux。

设置: var reload = require("require-reload")(require); var module_we_test = reload('...');

var linuxOsMock = {
    type: function () {
        return "Linux";
    }
};

var windowsOsMock = {
    type: function () {
        return "Windows_NT";
    }
};


describe('#the_module_we_test', function() {
    before(function() {
        mockery.enable({
            warnOnReplace: false
        });
    });
    after(function() {
        mockery.disable();
    });
    describe('#windows', function() {
        before(function() {
            mockery.registerMock('os', windowsOsMock);
            module_we_test = reload('...');
        });
        describe('#functionality A', function() {
            it('...', function() {
                /* tests functionality A which is OS dependnet */
                module_we_test.functionalityA();
            });
        });
    describe('#linux & darwin', function() {
        before(function() {
            mockery.registerMock('os', linuxOsMock);
            module_we_test = reload('...');
        });
        describe('#functionality A', function() {
            it('...', function() {
                /* tests functionality A which is OS dependnet */
                module_we_test.functionalityA();
            });
        });
    });
});

我在每个 OS 依赖测试夹具之前需要我正在测试的模块的原因是因为模块在全局范围内使用 OS 模块一次来决定一些变量值,就像这样:

var os = require('os');
var osType = os.type();

/* decide variable values based on os.type() return value */

所以,我认为除非我再次需要它,否则在每个 fixture 之前它将加载最初加载的 OS 模块而不是我的模拟。

现在,问题是它没有替换模块中的 OS 模块,我不知道为什么。

发生这种情况是因为您在上面做了 var module_we_test = require('...');。这将加载原始模块并将其保存在缓存中。因此,即使您每次需要它时都使用 mockery 来模拟它,您也会取回缓存的原始模块。您需要先使用 mockery 来模拟模块,然后 reload 模拟被测模块。重新加载的模块现在将检索模拟模块。您可以使用 [require-reload][1] 模块来完成此操作。

工作示例

describe('#the_module_we_test', function() {
    before(function() {
        mockery.enable({
            warnOnReplace: false
        });
    });
    after(function() {
        mockery.disable();
    });
    describe('#windows', function() {
        var module_we_test;
        before(function() {
            mockery.registerMock("os", windowsOsMock);
            module_we_test = reload("...");
        });
        after(function(){
            mockery.deregisterMock(windowsOsMock);
        });

        it("#functionality A", function() {
            /* tests functionality A which is OS dependnet */
            assert.equal(module_we_test.type(), "Windows_NT");
        });
    });
    describe('#linux', function() {
        var module_we_test;
        before(function() {
            mockery.registerMock("os", linuxOsMock);
            module_we_test = reload("...");
        });
        after(function(){
            mockery.deregisterMock(linuxOsMock);
        });

        it("#functionality A", function() {
            /* tests functionality A which is OS dependnet */
            assert.equal(module_we_test.type(), "Linux");
        });
    });
});

更新

仔细阅读mockery的文档后,似乎它提供了清理缓存的功能。所以不用 require-reload 你只需要设置

before(function() {
    mockery.enable({
        warnOnReplace: false,
        useCleanCache: true
    });
});

require 通常是加载模拟模块的模块。在 after 挂钩中 os 描述你需要调用 mockery.resetCache

after(function(){
    mockery.deregisterMock(windowsOsMock);
    mockery.resetCache();
}); 

我认为这是使用 mockery 模块解决这种情况的最佳方法