模拟本地存储以testing两种方法的function/覆盖

以下代码使用本地存储工作正常,我想为它创buildunit testing的问题是,我在这个函数中使用本地存储

这是我想testing的function

open: function(url) { var that = this; if (!localStorage.getItem(“alert”)) { that_run(url) .then(function(isBlocked) { if (isBlocked) { that._notify(); localStorage.setItem(“alert”, true); } else { localStorage.setItem(“alert”, true); that._exe(“page”,url) } }).done(); } else { that._exe(“page”,url) } }, 

这是正在工作的testing,但我认为重写窗口是不好的做法和我的问题,如果我能写这个testing更好?

 it.only("test for open", function () {    var url = "http://mytesturl”;    winlocalStorage.getItem = function(){        return false;    };    var oSimulateSpy = sandbox.spy(exc "_simulate");    return orun.open(url).then(function(){        expect(oSimulateSpy.called).to.be.true;    }); }); 

我看到这个post,这使用function编程https://stackoverflow.com/a/20153543/6124024,但我认为通过本地存储作为参数在这种情况下有点矫枉过正,因为这个函数(打开)被调用了很多次很多地方…有没有更好的/更清洁的方式来处理这个问题?

因为你的代码被加载了各种各样的副作用,所以你挣扎着。 因为您不会从this._exethat_run返回任何值,所以在我看来这些函数也有副作用。 你最好从这些函数返回值或Promised值,而不是依赖这些函数来改变更多的外部状态。

这里有一个更好的方法来编写你的模块

 // use "wrapper" function that configures this module export default function(storage) { return { // other functions ... async open (url) { if (storage.getItem('alert')) { return this._exe('page', url) // make sure _exe returns promise } else if (await that_run(url)) { storage.setItem('alert', true) return this.notify() // make sure notify returns Promise // or return Promise.resolve() } else { storage.setItem('alert', true) return this._exe('page', url) } } } 

在testing代​​码中使用你的模块

 // import mock storage adapter const MockStorage = require('./mock-storage'); // create mock storage adapter const mockStorage = new MockStorage(); // pass mock storage adapter to your module as a config argument const myModule = require('./my-module')(mockStorage); // don't forget to reset storage before each test beforeEach(function() { mockStorage.reset(); }); it("test for open", async function () { var url = "http://mytesturl"; mockStorage.set('alert', false); let someValue = await myModule.open(url); assert.equal(someValue, someExpectation); assert.equal(mockStorage.get('alert'), true); }); 

模拟存储适配器可能看起来像这样

 export default class MockStorage { constructor () { this.storage = new Map(); } setItem (key, value) { this.storage.set(key, value); } getItem (key) { return this.storage.get(key); } removeItem (key) { this.storage.delete(key); } clear () { this.constructor(); } } 

然后,当你在生产代码中使用你的模块时,你可以传递真正的localStorage

 // use window.localStorage as config argument in production code const myModule = require('./my-module')(window.localStorage);