【发布时间】:2013-01-26 20:32:07
【问题描述】:
目前,我有一个函数有时会返回一个包含一些函数的对象。使用expect(...).toEqual({...}) 时,它似乎与那些复杂的对象不匹配。具有函数或 File 类(来自输入类型文件)的对象,它就是不能。如何克服?
【问题讨论】:
目前,我有一个函数有时会返回一个包含一些函数的对象。使用expect(...).toEqual({...}) 时,它似乎与那些复杂的对象不匹配。具有函数或 File 类(来自输入类型文件)的对象,它就是不能。如何克服?
【问题讨论】:
expect(_.isEqual(obj1, obj2)).toEqual(true);
如果可行,您可以创建一个custom matcher:
this.addMatchers({
toDeepEqual: function(expected) {
return _.isEqual(this.actual, expected);
};
});
然后您可以编写如下规范:
expect(some_obj).toDeepEqual(expected_obj);
【讨论】:
toEqual 给我同样的结果=> Error: Expected { exception : Function, data : Function, proxy : Function, remote : Function, append_args : Function, set_args : Function, get_args : Function, remove : Function, make : Function, unmake : Function } to deep equal { exception : Function, data : Function, proxy : Function, remote : Function, append_args : Function, set_args : Function, get_args : Function, remove : Function, make : Function, unmake : Function }.
File 和 FileList 类
{},这明显是错误的,好像不能把函数转换成字符串(比如用@ 987654331@)
正如 Vlad Magdalin 在 cmets 中指出的那样,将对象制作成 JSON 字符串,它可以像它一样深,以及函数和 File/FileList 类。当然,在函数上不用toString(),也可以直接叫'Function'
function replacer(k, v) {
if (typeof v === 'function') {
v = v.toString();
} else if (window['File'] && v instanceof File) {
v = '[File]';
} else if (window['FileList'] && v instanceof FileList) {
v = '[FileList]';
}
return v;
}
beforeEach(function(){
this.addMatchers({
toBeJsonEqual: function(expected){
var one = JSON.stringify(this.actual, replacer).replace(/(\\t|\\n)/g,''),
two = JSON.stringify(expected, replacer).replace(/(\\t|\\n)/g,'');
return one === two;
}
});
});
expect(obj).toBeJsonEqual(obj2);
【讨论】:
如果有人像我一样使用 node.js,当我只关心比较简单属性而忽略所有功能时,我在 Jasmine 测试中使用以下方法。此方法需要json-stable-stringify,用于在序列化之前对对象属性进行排序。
用法:
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 中有效:
http://jasmine.github.io/2.0/custom_matcher.html
beforeEach(function() {
jasmine.addMatchers({
toDeepEqual: function(util, customEqualityTesters) {
return {
compare: function(actual, expected) {
var result = {};
result.pass = _.isEqual(actual, expected);
return result;
}
}
}
});
});
如果您使用 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";
/**
* 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);
});
});
【讨论】: