使用Jasmine的spyOn / andReturn来模拟fs.readFileSync()

时间:2016-08-03 06:32:58

标签: node.js express jasmine tdd

我正在尝试模拟fs.readFileSync()的响应,所以我可以测试我的代码在我的配置文件中返回一些数据。显然我不想测试配置文件的内容。

我正在尝试在(api.js)

中测试此代码
var fs = require('fs');
var config = JSON.parse(fs.readFileSync('configure.json', 'utf8'));

var Api = {
    api_key: config['api-key'],
    heartbeat_id: config['resource-id'],
};

如果我可以模拟fs.readFileSync返回的内容,那么我可以让它返回一些测试值。我的测试看起来像这样:

var api = require('./api');
var fs = require('fs');

describe('Api object contains correct details', function(){
    it('Has an API key of "test API"', function(){
        spyOn(fs, 'readFileSync').andReturn(`{
            "api-key": "test API",
            "resource-id": "Resource ID"
        }`);
        expect(api.api_key).toBe("test API");
    });
});

测试失败并在我的实际配置文件中返回值。

1 个答案:

答案 0 :(得分:2)

api.js中,您不会导出任何其他模块使用的内容,因此在您的测试文件中执行时...

var api = require('./api');

...您正在立即执行api.js文件。这意味着,当您的测试在fs.readFileSync上创建间谍时,api.js已使用该函数,并且您的值注入未在测试范围中使用。

实现目标的一种方法是在api.js中创建一个按需检索配置的函数,并将此函数封装在module.exports块中。然后,在您的测试中,要求api.js使测试准备好检索配置,因此如果您在进行检索之前在fs.readFileSync上创建了间谍,那么间谍就会被调用,您可以对模拟的价值断言。

使用Jasmine 2.4.1,它的外观如下:

的src / api.js

var fs = require('fs');

module.exports = {
    getConfig: function() {
        var config = JSON.parse(fs.readFileSync('./src/configure.json', 'utf8'));

        var Api = {
            api_key: config['api-key'],
            heartbeat_id: config['resource-id'],
        };

        return Api;
    }
}

规格/ api.spec.js

var api = require('../src/api'); // fs.readFileSync hasn't been used yet
var fs = require('fs');

describe('Api object contains correct details', function(){
    it('Has an API key of "test API"', function() {
        spyOn(fs, 'readFileSync').and.returnValue(`{ // here it's being mocked
            "api-key": "test API",
            "resource-id": "Resource ID"
        }`);
        var config = api.getConfig(); // now we are using the mock
        expect(config.api_key).toBe("test API");
    });
});