是否可以在JavaScript中模拟document.cookie?

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)

DEMO


mci*_*321 9

此实现允许覆盖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)


mae*_*ics 8

@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)


Yan*_*dal 6

以下是我在 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)