回答:
@chiedoの優れたソリューション
ただし、ES2015の構文を使用しているため、この方法で記述する方が少しクリーンだと感じました。
class LocalStorageMock {
constructor() {
this.store = {};
}
clear() {
this.store = {};
}
getItem(key) {
return this.store[key] || null;
}
setItem(key, value) {
this.store[key] = value.toString();
}
removeItem(key) {
delete this.store[key];
}
};
global.localStorage = new LocalStorageMock;
|| null
私のテストではを使用していたので、最新の冗談がちょうどそれを使用していたと思うので、私のテストは失敗しましたnot.toBeDefined()
。@Chiedoソリューションが再び機能する
これの助けを借りてそれを理解しました:https ://groups.google.com/forum/#!topic/jestjs/9EPhuNWVYTg
次の内容のファイルをセットアップします。
var localStorageMock = (function() {
var store = {};
return {
getItem: function(key) {
return store[key];
},
setItem: function(key, value) {
store[key] = value.toString();
},
clear: function() {
store = {};
},
removeItem: function(key) {
delete store[key];
}
};
})();
Object.defineProperty(window, 'localStorage', { value: localStorageMock });
次に、Jest設定の下のpackage.jsonに次の行を追加します
"setupTestFrameworkScriptFile":"PATH_TO_YOUR_FILE",
"setupFiles": [...]
同様に動作します。配列オプションを使用すると、モックを個別のファイルに分離できます。例:"setupFiles": ["<rootDir>/__mocks__/localStorageMock.js"]
getItem
、特定のキーに対してデータが設定されていない場合にブラウザから返される値とは少し異なります。getItem("foo")
設定されていないときに呼び出すと、たとえばnull
ブラウザに戻りますがundefined
、このモックによって-これにより、テストの1つが失敗しました。私にとっての簡単な解決策store[key] || null
は、getItem
関数に戻ることでした
localStorage['test'] = '123'; localStorage.getItem('test')
create-react-appを使用している場合は、ドキュメントで説明されているよりシンプルで簡単なソリューションがあります。
これを作成してsrc/setupTests.js
、その中に入れます。
const localStorageMock = {
getItem: jest.fn(),
setItem: jest.fn(),
clear: jest.fn()
};
global.localStorage = localStorageMock;
以下のコメントでのトム・メルツの貢献:
次に、localStorageMockの関数が使用されていることを、次のようにテストできます。
expect(localStorage.getItem).toBeCalledWith('token')
// or
expect(localStorage.getItem.mock.calls.length).toBe(1)
呼び出されたことを確認したい場合は、テストの内部。https://facebook.github.io/jest/docs/en/mock-functions.htmlを確認してください
localStorage
。コードで使用するものを自動的にモックするだけです。(あなたが使用しcreate-react-app
、それが自然に提供するすべての自動スクリプトの場合)
expect(localStorage.getItem).toBeCalledWith('token')
またはexpect(localStorage.getItem.mock.calls.length).toBe(1)
内部でlocalStorageMockの関数が使用されていることをテストできます。facebook.github.io/jest/docs/en/mock-functions.htmlを
localStorage
か?各テストの後にスパイをリセットして、他のテストへの「スピルオーバー」を防止したくないですか?
現在(10月19日)、localStorageは、通常のように、およびcreate-react-appのドキュメントで概説されているように、jestによってモックまたはスパイすることはできません。これは、jsdomで行われた変更が原因です。あなたはそれについてjestとjsdom issue trackerで読むことができます。
回避策として、代わりにプロトタイプをスパイすることができます。
// does not work:
jest.spyOn(localStorage, "setItem");
localStorage.setItem = jest.fn();
// works:
jest.spyOn(window.localStorage.__proto__, 'setItem');
window.localStorage.__proto__.setItem = jest.fn();
// assertions as usual:
expect(localStorage.setItem).toHaveBeenCalled();
jest.spyOn(window.localStorage.__proto__, 'setItem');
または、次のようなモックパッケージを使用します。
https://www.npmjs.com/package/jest-localstorage-mock
ストレージ機能だけでなく、ストアが実際に呼び出されたかどうかをテストすることもできます。
undefined
値を処理し(を持たないtoString()
)、null
値が存在しない場合に戻る、より良い代替手段。これをreact
v15でテストしredux
、redux-auth-wrapper
class LocalStorageMock {
constructor() {
this.store = {}
}
clear() {
this.store = {}
}
getItem(key) {
return this.store[key] || null
}
setItem(key, value) {
this.store[key] = value
}
removeItem(key) {
delete this.store[key]
}
}
global.localStorage = new LocalStorageMock
removeItem
:developer.mozilla.org/en-US/docs/Web/API/Storage/removeItem
あなたがスタブではなくモックを探しているなら、これが私が使う解決策です:
export const localStorageMock = {
getItem: jest.fn().mockImplementation(key => localStorageItems[key]),
setItem: jest.fn().mockImplementation((key, value) => {
localStorageItems[key] = value;
}),
clear: jest.fn().mockImplementation(() => {
localStorageItems = {};
}),
removeItem: jest.fn().mockImplementation((key) => {
localStorageItems[key] = undefined;
}),
};
export let localStorageItems = {}; // eslint-disable-line import/no-mutable-exports
初期化を簡単にするために、ストレージアイテムをエクスポートします。IE簡単にオブジェクトに設定できます
Jest + JSDomの新しいバージョンでは、これを設定することはできませんが、localstorageはすでに利用可能であり、次のようにスパイすることができます。
const setItemSpy = jest.spyOn(Object.getPrototypeOf(window.localStorage), 'setItem');
私はgithubからこの解決策を見つけました
var localStorageMock = (function() {
var store = {};
return {
getItem: function(key) {
return store[key] || null;
},
setItem: function(key, value) {
store[key] = value.toString();
},
clear: function() {
store = {};
}
};
})();
Object.defineProperty(window, 'localStorage', {
value: localStorageMock
});
このコードをsetupTestsに挿入すると、問題なく機能するはずです。
typesctiptを使用したプロジェクトでテストしました。
@ ck4が提案したドキュメントにはlocalStorage
、jest での使用に関する明確な説明があるためです。ただし、モック関数は、localStorage
メソッドの。
以下は、データの書き込みと読み取りに抽象的なメソッドを使用する私のreactコンポーネントの詳細な例です。
//file: storage.js
const key = 'ABC';
export function readFromStore (){
return JSON.parse(localStorage.getItem(key));
}
export function saveToStore (value) {
localStorage.setItem(key, JSON.stringify(value));
}
export default { readFromStore, saveToStore };
エラー:
TypeError: _setupLocalStorage2.default.setItem is not a function
修正:
冗談のためのモック機能の下に追加(パス:.jest/mocks/setUpStore.js
)
let mockStorage = {};
module.exports = window.localStorage = {
setItem: (key, val) => Object.assign(mockStorage, {[key]: val}),
getItem: (key) => mockStorage[key],
clear: () => mockStorage = {}
};
ここからスニペットを参照
Typescriptを使用するプロジェクトの問題を解決するために、ここで他のいくつかの回答をリフしました。私は次のようなLocalStorageMockを作成しました:
export class LocalStorageMock {
private store = {}
clear() {
this.store = {}
}
getItem(key: string) {
return this.store[key] || null
}
setItem(key: string, value: string) {
this.store[key] = value
}
removeItem(key: string) {
delete this.store[key]
}
}
次に、LocalStorageWrapperクラスを作成しました。これは、グローバルローカルストレージ変数に直接アクセスする代わりに、アプリのローカルストレージへのすべてのアクセスに使用します。テスト用のラッパーにモックを簡単に設定できるようになりました。
describe('getToken', () => {
const Auth = new AuthService();
const token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6Ik1yIEpvc2VwaCIsImlkIjoiNWQwYjk1Mzg2NTVhOTQ0ZjA0NjE5ZTA5IiwiZW1haWwiOiJ0cmV2X2pvc0Bob3RtYWlsLmNvbSIsInByb2ZpbGVVc2VybmFtZSI6Ii9tcmpvc2VwaCIsInByb2ZpbGVJbWFnZSI6Ii9Eb3Nlbi10LUdpci1sb29rLWN1dGUtbnVrZWNhdDMxNnMtMzExNzAwNDYtMTI4MC04MDAuanBnIiwiaWF0IjoxNTYyMzE4NDA0LCJleHAiOjE1OTM4NzYwMDR9.YwU15SqHMh1nO51eSa0YsOK-YLlaCx6ijceOKhZfQZc';
beforeEach(() => {
global.localStorage = jest.fn().mockImplementation(() => {
return {
getItem: jest.fn().mockReturnValue(token)
}
});
});
it('should get the token from localStorage', () => {
const result = Auth.getToken();
expect(result).toEqual(token);
});
});
モックを作成してglobal
オブジェクトに追加する
このスニペットでローカルストレージをモックする必要があります
// localStorage.js
var localStorageMock = (function() {
var store = {};
return {
getItem: function(key) {
return store[key] || null;
},
setItem: function(key, value) {
store[key] = value.toString();
},
clear: function() {
store = {};
}
};
})();
Object.defineProperty(window, 'localStorage', {
value: localStorageMock
});
そしてjest設定で:
"setupFiles":["localStorage.js"]
何でもお気軽にどうぞ。
次のソリューションは、より厳密なTypeScript、ESLint、TSLint、およびPrettier構成でのテストと互換性があります{ "proseWrap": "always", "semi": false, "singleQuote": true, "trailingComma": "es5" }
。
class LocalStorageMock {
public store: {
[key: string]: string
}
constructor() {
this.store = {}
}
public clear() {
this.store = {}
}
public getItem(key: string) {
return this.store[key] || undefined
}
public setItem(key: string, value: string) {
this.store[key] = value.toString()
}
public removeItem(key: string) {
delete this.store[key]
}
}
/* tslint:disable-next-line:no-any */
;(global as any).localStorage = new LocalStorageMock()
HT / https://stackoverflow.com/a/51583401/101290(global.localStorageの更新方法)
Typescriptで同じことを行うには、次のようにします。
次の内容のファイルをセットアップします。
let localStorageMock = (function() {
let store = new Map()
return {
getItem(key: string):string {
return store.get(key);
},
setItem: function(key: string, value: string) {
store.set(key, value);
},
clear: function() {
store = new Map();
},
removeItem: function(key: string) {
store.delete(key)
}
};
})();
Object.defineProperty(window, 'localStorage', { value: localStorageMock });
次に、Jest設定の下のpackage.jsonに次の行を追加します
"setupTestFrameworkScriptFile":"PATH_TO_YOUR_FILE",
または、ローカルストレージをモックしたいテストケースにこのファイルをインポートします。
value + ''
nullと未定義の値を正しく処理するために、おそらくセッターで行う必要があります