如何在JavaScript中测试具有不同参数值的两个返回函数?

时间:2019-06-28 10:42:06

标签: javascript angular jasmine karma-webpack

我有一个返回比较功能的函数

  getComparisonFunction(propertyOfComparison) {
    const func = function(a, b){
      if ( a[propertyOfComparison] < b[propertyOfComparison] ) {
        return -1;
      }
      if ( a[propertyOfComparison] > b[propertyOfComparison] ) {
        return 1;
      }
      return 0;
    };

    return func;
  }

此方法将在javascript“ sort”方法中使用。 例如:

arrayOfObjects.sort(getComparisonFunction('name'));

此方法将按“名称”属性对“ arrayOfObjects”进行排序。 方法工作正常,问题是: 如何比较具有不同参数的函数调用

  it('should get correct comparison function', function () {
    const func = component.getComparisonFunction('testProperty');

    const expectedFunc = function(a, b){
      if ( a['testProperty'] < b['testProperty'] ) {
        return -1;
      }
      if ( a['testProperty'] > b['testProperty'] ) {
        return 1;
      }
      return 0;
    };

    expect(func.toString()).toEqual(expectedFunc.toString());
  });

这是我现在所拥有的,但是它不起作用。运行代码后我收到的错误是:

 Expected 'function (a, b) {
                if (a[propertyOfComparison] < b[propertyOfComparison]) {
                    return -1;
                }
                if (a[propertyOfComparison] > b[propertyOfComparison]) {
                    return 1;
                }
                return 0;
            }' to equal 'function (a, b) {
                if (a['testProperty'] < b['testProperty']) {
                    return -1;
                }
                if (a['testProperty'] > b['testProperty']) {
                    return 1;
                }
                return 0;
            }'.

2 个答案:

答案 0 :(得分:2)

将功能代码作为测试进行检查 非常 易碎,并且容易折断,从而给您一个假的否定之词:

let someFn = function(a, b) {
  return a + b;
}

let expected = `function(a, b) {
  return a + b;
}`

console.log("Test original implementation:", test(someFn.toString(), expected));

//later the code style is changed to remove extra whitespace and make it one line
someFn = function(a, b) { return a+b; }

console.log("Test updated implementation:", test(someFn.toString(), expected));

//simple testing
function test(expected, actual) {
  return expected == actual
}

仅对代码进行非功能性更改会破坏测试。

更糟糕的是,如果对代码进行了 功能更改,则测试不能保证新实现的行为与旧实现相同,因为它仅查看代码的结构:

//simplified case of what the actual code could be doing
function someCodeBaseFunction() {
  let someInput = [8, 12, 42];
  return someFn(...someInput)
}

let someFn = function(a, b) { return a+b; }

let expected = `function(a, b) { return a+b; }`

console.log("Test original implementation:", test(someFn.toString(), expected));

console.log("Codebase usage:", someCodeBaseFunction()); //20, as the third number is ignored

//new implementation
someFn = function(...args) { 
  return args.reduce((a, b) => a + b); 
}

//update the test, so it passes
expected = `function(...args) { 
  return args.reduce((a, b) => a + b); 
}`

console.log("Test updated implementation:", test(someFn.toString(), expected));

//some existing line of code
console.log("Codebase usage:", someCodeBaseFunction()); //62, as the third number is now used

//simple testing
function test(expected, actual) {
  return expected == actual
};

相反,您要执行的操作将测试代码的行为并在此处设置您的期望。这样,如果实现发生更改,则可以确保实现仍然符合同一组期望。

在这种情况下,您需要创建一个示例输入,该输入最初是无序的,尝试对其进行排序,然后期望该命令按预期工作。用伪代码看起来像这样:

//arrange
input = [
 {testProperty: "c", id: 1},
 {testProperty: "a", id: 2},
 {testProperty: "d", id: 3},
 {testProperty: "b", id: 4}
];

expected = [
 {testProperty: "a", id: 2},
 {testProperty: "b", id: 4},
 {testProperty: "c", id: 1},
 {testProperty: "d", id: 3}
];

//act
input.sort(component.getComparisonFunction('testProperty'))

//assert
expect(input).toEqual(expected);

如果需要,还可以在更详细的级别上添加更多测试,以进一步约束期望。例如,如果您要确保比较区分大小写

//arrange
a = { testProperty: "a" };
b = { testProperty: "B" };

//act
result = component.getComparisonFunction('testProperty')(a, b)

//assert
expect(result).toBeGreaterThanOrEqual(1)

或不区分大小写:

//arrange
a = { testProperty: "a" };
b = { testProperty: "B" };

//act
result = component.getComparisonFunction('testProperty')(a, b)

//assert
expect(result).toBeLessThanOrEqual(-1)

这更加清晰地定义了您的期望,并确保将来的更改将完全满足您的需求。

答案 1 :(得分:0)

如果要通过提供的任何参数实现排序,可以尝试以下操作:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/blue"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
tools:context="com.yourappname.MainActivity"
tools:showIn="@layout/app_bar_main">

此外,要对其进行测试,只需具有上述测试用例,并检查其是否按照您的实现进行排序。