以下代码使用了按预期工作的本地存储,我想为它创建单元测试问题是我在此函数中使用本地存储
这是我要测试的功能
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)
}
},
这是正在进行的测试,但我认为重写窗口是不好的做法,我的问题是否可以更好地编写此测试?
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;
});
});
我看过这篇文章,并使用了功能编程 https://stackoverflow.com/a/20153543/6124024 但是我认为在这种情况下传递本地存储作为参数有点矫枉过正,因为这个函数(open)在很多地方被多次调用...是否有更好/更清晰的方法来处理它?</ p>
答案 0 :(得分:1)
你的挣扎是因为你的代码加载了各种各样的副作用。因为您没有从this._exe
或that_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)
}
}
}
在测试代码中使用您的模块
// 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);