thi*_*eek 23 javascript unit-testing
document.cookie就像一个字符串,但它不是一个字符串.引用Mozilla文档中的示例:
document.cookie = "name=oeschger";
document.cookie = "favorite_food=tripe";
alert(document.cookie);
// displays: name=oeschger;favorite_food=tripe
Run Code Online (Sandbox Code Playgroud)
如果您尝试仅使用字符串制作模拟cookie,则不会得到相同的结果:
var mockCookie = "";
mockCookie = "name=oeschger";
mockCookie = "favorite_food=tripe";
alert(mockCookie);
// displays: favorite_food=tripe
Run Code Online (Sandbox Code Playgroud)
所以,如果你想对运行在cookie上的模块进行单元测试,并且你想为这些测试使用模拟cookie,你呢?怎么样?
Fel*_*ing 18
您可以使用cookiesetter和getter 创建一个对象.这是一个非常简单的实现:
var mock = {
value_: '',
get cookie() {
return this.value_;
},
set cookie(value) {
this.value_ += value + ';';
}
};
Run Code Online (Sandbox Code Playgroud)
可能不适用于所有浏览器(尤其是IE).更新:它仅适用于支持ECMAScript 5的浏览器!
mock.cookie = "name=oeschger";
mock.cookie = "favorite_food=tripe";
alert(mock.cookie);
// displays: name=oeschger;favorite_food=tripe;
Run Code Online (Sandbox Code Playgroud)
此实现允许覆盖cookie,并添加 document.clearCookies()
(function (document) {
var cookies = {};
document.__defineGetter__('cookie', function () {
var output = [];
for (var cookieName in cookies) {
output.push(cookieName + "=" + cookies[cookieName]);
}
return output.join(";");
});
document.__defineSetter__('cookie', function (s) {
var indexOfSeparator = s.indexOf("=");
var key = s.substr(0, indexOfSeparator);
var value = s.substring(indexOfSeparator + 1);
cookies[key] = value;
return key + "=" + value;
});
document.clearCookies = function () {
cookies = {};
};
})(document);
Run Code Online (Sandbox Code Playgroud)
@Felix Kling的答案是正确的,我只是想指出在ECMAScript 5中有一个定义setter和getter的替代语法:
function MockCookie() {
this.str = '';
this.__defineGetter__('cookie', function() {
return this.str;
});
this.__defineSetter__('cookie', function(s) {
this.str += (this.str ? ';' : '') + s;
return this.str;
});
}
var mock = new MockCookie();
mock.cookie = 'name=oeschger';
mock.cookie = 'favorite_food=tripe';
mock.cookie; // => "name=oeschger;favorite_food=tripe"
Run Code Online (Sandbox Code Playgroud)
同样,大多数浏览器都支持ECMAScript 5(由ECMA-262第5版定义),但不支持 MSIE(或JScript).
小智 7
我发现 jasminespyOnProperty可以用来监视对象的 getter 和 setter。所以我用这个解决了我的问题:
const cookie: string = 'my-cookie=cookievalue;';
spyOnProperty(document, 'cookie', 'get').and.returnValue(cookie);
Run Code Online (Sandbox Code Playgroud)
以下是我在 Jest 中最终的做法:
document.cookie添加属性后,我的 cookie 不再添加Secure(因为document.location不安全http://localhost)。
因此,经过大量的试验和错误(尝试拦截document.cookie的 setter 并将其;Secure从中删除,但随后使用document.cookie = 新值再次调用,当它再次进入 setter 时触发了无限循环......),我最终得到了这个非常简单的结果解决方案:
beforeEach(function() {
let cookieJar = document.cookie;
jest.spyOn(document, 'cookie', 'set').mockImplementation(cookie => {
cookieJar += cookie;
});
jest.spyOn(document, 'cookie', 'get').mockImplementation(() => cookieJar);
})
Run Code Online (Sandbox Code Playgroud)