我有一个带有react和redux的应用程序。我的测试引擎是 - Chai
在我的reducer( src / my_reducer.js )中,我尝试从localStorage获取令牌,如下所示:
const initialState = {
profile: {},
token: window.localStorage.getItem('id_token') ? window.localStorage.getItem('id_token') : null,
}
在我的测试文件( test / reducer_spec.js )中,我在测试用例之前导入了'my_reducer':
import myReducer from '../src/my_reducer'
我有一个错误,如果我尝试运行test - localStorage(或window.localStorage) - undefined。
我需要嘲笑localStorage吗?如果我需要,它的位置在哪里?
答案 0 :(得分:4)
我用mock-local-storage解决问题 我的运行测试命令是:
mocha -r mock-local-storage --compilers js:babel-core/register --recursive
答案 1 :(得分:4)
我认为你正在使用摩卡运行测试? mocha测试在node.js中运行,而node.js没有全局窗口变量。但您可以在测试中轻松创建一个:
global.window = {};
您甚至可以立即将localStorage添加到其中:
global.window = { localStorage: /* your mock localStorage */ }
模拟取决于您在本地存储中存储的内容,但对于上面的示例代码,这可能是一个合理的模拟对象:
var mockLocalStorage = {
getItem: function (key) {
if( key === 'id_token' ){ return /* a token object */; }
return null;
}
}
当然,对于不同的测试,你可以有不同的模拟,例如另一个模拟可能总是返回null
来测试无法找到密钥的情况。
答案 2 :(得分:2)
出于测试目的,我建议不进行任何可能产生副作用的调用或在声明中调用外部模块。
因为需要/导入你的reducer隐式调用window.localStorage.getItem(...)
干净的测试变得很难。
我建议使用init
方法包装初始化代码,这样如果在调用init
之前需要/导入模块,则不会发生任何事情。然后,您可以使用beforeEach
afterEach
来干净地设置模拟/沙箱。
import myReducer from '../src/my_reducer'
describe('with faked localStorage', function() {
var sandbox
beforeEach(function() {
sandbox = sinon.sandbox.create()
// fake window.localStorage
})
afterEach(function() {
sandbox.restore()
})
describe('the reducer', function() {
before(function() {
myReducer.init()
})
})
})
第二个最佳解决方案是推迟导入并在require
测试挂钩中使用before
。
describe('with fake localStorage', function() {
var sandbox
beforeEach(function() {
sandbox = sinon.sandbox.create()
// fake window.localStorage
})
afterEach(function() {
sandbox.restore()
})
describe('the reducer', function() {
var myReducer
before(function() {
myReducer = require('../src/my_reducer')
})
})
})
答案 3 :(得分:1)
这是因为您没有在浏览器环境中运行Chai。
尝试:
// Make sure there is a window object available, and that it has localstorage (old browsers don't)
const initialState = {
profile: {},
// window.localStorage.getItem('id_token') will return null if key not found
token: window && window.localStorage ? window.localStorage.getItem('id_token') : null,
}