繁体   English   中英

如何使用Jasmine对带有回报的多个链接函数进行单元测试?

[英]How to unit test with Jasmine on multiple chained functions with returns?

我有以下功能:

/**
* filters array down to the given allowed keys
* @param {Object} data
* @param {String[]} allowedKeys
*/
$scope.filterData = function(data, allowedKeys) {
    return Object.keys(data)
        .filter(function(key) {
            return allowedKeys.includes(key);
        })
        .reduce(function(obj, key) {
            obj[key] = data[key];
            return obj;
        }, {});
};

我要为其创建单元测试,到目前为止,我具有以下内容:

describe('$scope.filterData', function() { 
        //params
        var data = {
            key1: "value1",
            key2: "value2",
            key3: "value3"
        }
        var allowedKeys = ["key1", "key2"];
        //mockobject
        var $Object = jasmine.createSpyObj('Object', ['keys', 'filter', 'reduce']);

        it('should func', function() {

            $Object.keys.and.returnValue($Object);
            $Object.filter.and.returnValue($Object);
            $Object.reduce.and.returnValue($Object);

            $scope.filterData(data, allowedKeys);
            expect(Object.filter).toHaveBeenCalled();
        });
    });

我遇到的问题是出现以下错误:

TypeError:undefined不是构造函数(评估'allowedKeys.includes(key)')

我不明白,该如何解决该错误?

我不知道这种解决方案是否可以帮助您
当我们编写测试用例,特别是对功能的测试时,我们倾向于测试功能的输入和输出值。
对我来说,我认为我们不应该通过调用茉莉花模拟来接触Array, Object的原始功能。
如果您想知道函数在这种情况下是否正常运行。

例如:

describe('$scope.filterData', function() { 
    //params
    var data = {
        key1: "value1",
        key2: "value2",
        key3: "value3"
    }
    var allowedKeys = ["key1", "key2"];

    it('should return 2 key', function() {            
        var expected = {
          key1: "value1",
          key2: "value2",
        }

        var value = $scope.filterData(data, allowedKeys);
        expect(JSON.stringify(value)).toEqual(JSON.stringify());
    });
});

当然,有时我们必须模拟某些功能,例如当我们有http请求并且必须等待时,或者我们有其他地方的功能要使用并且想要模拟它们。
但是在这种情况下,您的函数并不是真正expect to be called某个函数,它就足够了,并且不依赖任何其他函数。
所以最好只关注函数的输入和输出值

首先, Object没有函数filter而您的jasmine.createSpyObj实际上是无用的。 正如@Luan Phan在回答中所说,我们通常倾向于测试该函数的输入和输出值。 Javascript内置函数无需在我们的测试中进行测试。

但是,例如,如果您想知道是否在函数内部调用了Object.keys ,则可以举一个例子

it('should func', function () {                        
    spyOn(Object, 'keys').and.callThrough();

    $scope.filterData(data, allowedKeys);                     

    expect(Object.keys).toHaveBeenCalled();
});

对于filterData中使用的其余内置函数,可以这样做

it('should func', function () {
    spyOn(Object, 'keys').and.callThrough();
    spyOn(Array.prototype, 'filter').and.callThrough();
    spyOn(Array.prototype, 'reduce').and.callThrough();

    $scope.filterData(data, allowedKeys);

    expect(Object.keys).toHaveBeenCalled();
    expect(Array.prototype.filter).toHaveBeenCalled();
    expect(Array.prototype.reduce).toHaveBeenCalled();
});

如果您真的需要模拟其中一个内置函数返回的内容,请参考以下示例

it('should func', function () {
    const mockResult = {};

    spyOn(Array.prototype, 'reduce').and.returnValue(mockResult);

    const result = filterData(data, allowedKeys);

    expect(result).toBe(mockResult);
});

同样,Javascript的内置函数已经在其他地方编写了测试,我们不需要在测试中对其进行测试,我们的重点应该放在编写的函数上。

希望能帮助到你

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM