Jasmine toEqual用于复杂对象(与函数混合)

Jasmine toEqual用于复杂对象(与函数混合),jasmine,matcher,Jasmine,Matcher,目前,我有一个函数,它有时返回一个包含一些函数的对象。使用expect(…).toEqual({…})时,它似乎与那些复杂对象不匹配。对象具有函数或文件类(来自输入类型文件),它就是不能。如何克服此问题?尝试以下功能: expect(_.isEqual(obj1, obj2)).toEqual(true); 如果可行,您可以创建一个: 然后,您可以编写如下规格: expect(some_obj).toDeepEqual(expected_obj); 正如Vlad Magdalin在评论中指出

目前,我有一个函数,它有时返回一个包含一些函数的对象。使用
expect(…).toEqual({…})
时,它似乎与那些复杂对象不匹配。对象具有函数或
文件
类(来自输入类型文件),它就是不能。如何克服此问题?

尝试以下功能:

expect(_.isEqual(obj1, obj2)).toEqual(true);
如果可行,您可以创建一个:

然后,您可以编写如下规格:

expect(some_obj).toDeepEqual(expected_obj);

正如Vlad Magdalin在评论中指出的那样,将对象设置为JSON字符串,它可以是最深的,函数和文件/文件列表类。当然,它可以被称为“函数”,而不是函数上的
toString()

函数替换器(k,v){
如果(v的类型==='函数'){
v=v.toString();
}else if(窗口['File']&&v文件实例){
v=“[文件]”;
}else if(窗口['FileList']&&v文件列表实例){
v=“[FileList]”;
}
返回v;
}
beforeach(函数(){
这是addMatchers({
toBeJsonEqual:函数(预期){
var one=JSON.stringify(this.actual,replace).replace(/(\\t |\\n)/g',),
two=JSON.stringify(应为replace).replace(/(\\t |\\n)/g');
返回1==2;
}
});
});
expect(obj).toBeJsonEqual(obj2);

如果有人像我一样使用node.js,那么下面的方法就是我在Jasmine测试中使用的方法,我只关心比较简单属性,而忽略所有函数。此方法需要在序列化之前用于对对象属性进行排序的

用法:

  var stringify = require('json-stable-stringify');

  var obj1 = {
    func: function() {
    },
    str1: 'str1 value',
    str2: 'str2 value',
    nest1: {
    nest2: {
        val1:'value 1',
        val2:'value 2',
        someOtherFunc: function() {
        }
      }
    }
  };

  var obj2 = {
    str2: 'str2 value',
    str1: 'str1 value',
    func: function() {
    },
    nest1: {
      nest2: {
        otherFunc: function() {
        },
        val2:'value 2',
        val1:'value 1'
      }
    }
  };

  it('should compare object properties', function () {
    expect(stringify(obj1)).toEqual(stringify(obj2));
  });

扩展@Vlad Magdalin的答案,这在Jasmine 2中起作用:

如果您正在使用Karma,请将其放入启动回调中:

callback: function() {
  // Add custom Jasmine matchers.
  beforeEach(function() {
    jasmine.addMatchers({
      toDeepEqual: function(util, customEqualityTesters) {
        return {
          compare: function(actual, expected) {
            var result = {};
            result.pass = _.isEqual(actual, expected);
            return result;
          }
        }
      }
    });
  });

  window.__karma__.start();
});

下面是我如何使用
Jasmine 2
语法完成的

我在
。/support/customMatchers.js
中创建了一个customMatchers模块(我喜欢制作模块)

然后在我的测试中使用,如下所示:

"use strict";

let someExternalFunction = require('../../lib/someExternalFunction');
let thingBeingTested = require('../../lib/thingBeingTested');

let customMatchers = require('../support/customMatchers');

describe('myTests', function() {

  beforeEach(function() {
    jasmine.addMatchers(customMatchers);

    let app = {
      use: function() {}
    };

    spyOn(app, 'use');
    thingBeingTested(app);
  });

  it('calls app.use with the correct function', function() {
    expect(app.use.calls.count()).toBe(1);
    expect(app.use.calls.argsFor(0)).toBeTheSameFunctionAs(someExternalFunction);
  });

});

toEqual
=>
错误中给出相同的结果:预期{异常:函数、数据:函数、代理:函数、远程:函数、追加参数:函数、设置参数:函数、获取参数:函数、删除:函数、生成:函数、取消生成:函数}为深度相等{异常:函数,数据:函数,代理:函数,远程:函数,附加参数:函数,设置参数:函数,获取参数:函数,删除:函数,生成:函数,取消生成:函数}.
您正在比较的对象是否仅由函数组成?在这种情况下,是的,但有时我会使用类以及普通对象和本机包装器,例如
文件
文件列表
类(JSON.stringify)有效…在你接受修改后我会接受你的答案:)实际上,它不起作用,在检查该函数的输出后,它显示为
{}
,这显然是错误的,它似乎无法将函数转换为字符串(如使用
(function(){}).toString()
)请注意,JSON.stringify不保证属性顺序!因此比较生成的JSON可能会导致随机测试失败。这取决于底层javascript运行程序如何对属性进行排序。例如:测试可能在engineA(例如NodeJS)中运行,但在engineB(例如Firefox)中中断甚至在另一个engineA版本中。或者在同一版本的同一个引擎中运行时随机均衡。
callback: function() {
  // Add custom Jasmine matchers.
  beforeEach(function() {
    jasmine.addMatchers({
      toDeepEqual: function(util, customEqualityTesters) {
        return {
          compare: function(actual, expected) {
            var result = {};
            result.pass = _.isEqual(actual, expected);
            return result;
          }
        }
      }
    });
  });

  window.__karma__.start();
});
"use strict";

/**
 *  Custom Jasmine matchers to make unit testing easier.
 */
module.exports = {
  // compare two functions.
  toBeTheSameFunctionAs: function(util, customEqualityTesters) {
    let preProcess = function(func) {
      return JSON.stringify(func.toString()).replace(/(\\t|\\n)/g,'');
    };

    return {
      compare: function(actual, expected) {
        return {
          pass: (preProcess(actual) === preProcess(expected)),
          message: 'The functions were not the same'
        };
      }
    };
  }
}
"use strict";

let someExternalFunction = require('../../lib/someExternalFunction');
let thingBeingTested = require('../../lib/thingBeingTested');

let customMatchers = require('../support/customMatchers');

describe('myTests', function() {

  beforeEach(function() {
    jasmine.addMatchers(customMatchers);

    let app = {
      use: function() {}
    };

    spyOn(app, 'use');
    thingBeingTested(app);
  });

  it('calls app.use with the correct function', function() {
    expect(app.use.calls.count()).toBe(1);
    expect(app.use.calls.argsFor(0)).toBeTheSameFunctionAs(someExternalFunction);
  });

});