【问题标题】:How do I unit test localStorage being undefined with Mocha/Sinon/Chai如何使用 Mocha/Sinon/Chai 对未定义的 localStorage 进行单元测试
【发布时间】:2015-03-28 14:03:16
【问题描述】:

我有 2 个简单的方法可以抽象出对 localStorage 的读写:

_readLocalStorage: function(key) {
    if (window.localStorage && window.localStorage.getItem(key)) {
        return JSON.parse(window.localStorage.getItem(key));
    } else {
        throw new Error('Could not read from localStorage');
    }
},

_writeLocalStorage: function(key, data) {
    try {
        window.localStorage.setItem(key, JSON.stringify(data));
    } catch (e) {
        throw new Error('Could not write to localStorage');
    }
},

显然,存根 window.localStorage.getItem/setItem 很简单。但是 localStorage 未定义的情况呢?

我已经尝试过缓存/解除 window.localStorage(第二个断言):

describe('#_readLocalStorage', function() {
    it('should read from localStorage', function() {
        // set up
        var stub1 = sinon.stub(window.localStorage, 'getItem')
        .returns('{"foo": "bar"}');

        // run unit
        var result = service._readLocalStorage('foo');

        // verify expectations
        expect(result)
        .to.eql({foo: 'bar'});

        // tear down
        stub1.restore();
    });

    it('should throw an error if localStorage is undefined', function() {
        // set up
        var cachedLocalStorage = window.localStorage;
        window.localStorage = undefined;

        // run unit/verify expectations
        expect(service._readLocalStorage('foo'))
        .to.throw(new Error('Could not write to localStorage'));

        // tear down
        window.localStorage = cachedLocalStorage;
    });
});

但这不起作用。 Mocha/Chai 似乎没有捕捉到抛出的错误。

我环顾四周,但找不到任何方法来处理这个问题。

【问题讨论】:

    标签: unit-testing local-storage mocha.js sinon chai


    【解决方案1】:

    你的expect应该是

    expect(service._readLocalStorage.bind(service, 'foo'))
        .to.throw(new Error('Could not write to localStorage'));
    

    你有它的方式你的代码调用service._readLocalStorage('foo')之前expect被调用。所以它引发了expect 无法处理的异常。 expect 需要能够处理异常的是expect 自身 将调用的函数。使用 service._readLocalStorage.bind(service, 'foo') 创建一个新函数,当不带参数调用时(如 expect 所做的那样)将等效于调用 service._readLocalStorage('foo')。

    您的测试还有另一个问题:您的清理代码永远不会执行。断言库通过引发 JavaScript 异常来报告问题。因此,除非对异常进行特殊处理,否则任何跟随失败异常的代码都不会运行。你可以这样做:

    it('should throw an error if localStorage is undefined', function() {
        // set up
        var cachedLocalStorage = window.localStorage;
        window.localStorage = undefined;
    
        // run unit/verify expectations
        try {
            expect(...)...;
            expect(...)...;
            ...
        }
        finally {
            // tear down
            window.localStorage = cachedLocalStorage;
        }
    });
    

    对于更复杂的情况,您应该使用before、beforeEach、after、afterEach 进行设置和拆卸。

    【讨论】:

    • DERP,当然不能在抛出异常后调用清理代码。感谢您的回答,效果很好。
    猜你喜欢
    • 2016-05-26
    • 2021-09-27
    • 2023-04-11
    • 2019-02-14
    • 2016-12-21
    • 2019-02-03
    • 2017-06-09
    • 2018-11-05
    • 1970-01-01
    相关资源
    最近更新 更多