簡體   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