web-dev-qa-db-ja.com

jestテストでlocalStorageを処理するにはどうすればよいですか?

Jestテストで「localStorageが定義されていません」と表示されるのは理にかなっていますが、私のオプションは何ですか?レンガの壁を打つ。

104
Chiedo

@ 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;
118
nickcan

これの助けを借りてそれを理解しました: 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 configsの下のpackage.jsonに次の行を追加します

"setupTestFrameworkScriptFile":"PATH_TO_YOUR_FILE",

78
Chiedo

Create-react-appを使用する場合は、 documentation で説明されているよりシンプルで簡単なソリューションがあります。

src/setupTests.jsを作成して、これを入れます:

const localStorageMock = {
  getItem: jest.fn(),
  setItem: jest.fn(),
  clear: jest.fn()
};
global.localStorage = localStorageMock;

以下のコメントでのTom Mertzの貢献:

次に、次のようなことを行うことで、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

45
c4k

または、次のような模擬パッケージを使用します。

https://www.npmjs.com/package/jest-localstorage-mock

ストレージ機能だけでなく、ストアが実際に呼び出されたかどうかをテストすることもできます。

14
Aligertor

現在(Jan '19)localStorageは、通常のように、またcreate-react-app docsで概説されているように、jestによってモックやスパイを行うことはできません。これは、jsdomで行われた変更によるものです。あなたはここでそれを読むことができます https://github.com/facebook/jest/issues/6798 そしてここで https://github.com/jsdom/jsdom/issues/2318

回避策として、代わりにプロトタイプをスパイできます。

// 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();
12
Bastian Stein

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
11
Dmitriy

@ ck4が示唆したように、 documentation にはjestでlocalStorageを使用するための明確な説明があります。ただし、モック関数は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の下にモック関数を追加(パス:.jest/mocks/setUpStore.js

let mockStorage = {};

module.exports = window.localStorage = {
  setItem: (key, val) => Object.assign(mockStorage, {[key]: val}),
  getItem: (key) => mockStorage[key],
  clear: () => mockStorage = {}
};

スニペットは here から参照されます

3
Mad-D

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クラスを作成しました。テストのラッパーにモックを簡単に設定できるようにしました。

2
CorayThan

スタブではなくモックを探している場合、私が使用するソリューションは次のとおりです。

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

初期化を簡単にするために、ストレージアイテムをエクスポートします。 I.E.オブジェクトに簡単に設定できます

Jest + JSDomの新しいバージョンでは、これを設定することはできませんが、localstorageはすでに利用可能であり、次のようにスパイすることができます。

const setItemSpy = jest.spyOn(Object.getPrototypeOf(window.localStorage), 'setItem');
1
TigerBear
    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オブジェクトに追加します

1
Trevor Joseph

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を使用したプロジェクトでテストしました。

1
Carlos Huamani

Storageオブジェクトのプロトタイプをスパイする必要があります。

const spy = jest.spyOn(Storage.prototype, 'getItem');

そしてその後、次のように主張します:

expect(spy).toHaveBeenCalledWith(somevalue);
0
user3568791

次のソリューションは、より厳密なTypeScript、ESLint、TSLint、およびPrettier configを使用したテストと互換性があります:{ "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/10129 global.localStorageの更新方法

0
Beau Smith