質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.78%

LocalStorageのテストで作ったmockのlengthの挙動がおかしい【angularCLI】

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 590

kanegazaki

score 15

前提・実現したいこと

angularCLIを使っています。
ブラウザのローカルストレージを使うサービスクラスのテストがしたいです。

試したこと

LocalStorageのテストなのでmockを作りました。
LocalStorageに3つのデータが入っていれば
LocalStorage.lengthは3が返ってくるはずで、実際のブラウザで試したら3が返ってきました。
しかしテストコードのmockだと3ではなく0が返ってきます。

TokenServiceのテストのここが怪しいと思ったんですが
文法的に問題なさそうでした。

      length: () => {
        return Object.keys(store).length;
      }

正しい挙動にするにはどうしたからよいですか。

TokenService

import {Injectable} from '@angular/core';

@Injectable()
export class TokenService {
  private TOKEN_KEY = 'id_token';

  constructor() {
  }

  setAccessToken(token: string) {
    localStorage.setItem(this.TOKEN_KEY, token);
  }

  getAccessToken(): string {
    return localStorage.getItem(this.TOKEN_KEY);
  }

  getAccessTokenNum() {
    return localStorage.length;
  }
}


TokenServiceのテスト

import {TestBed} from '@angular/core/testing';

import {TokenService} from './token-service.service';

describe('TokenService', () => {
  let service: TokenService;

  beforeEach(() => {
    TestBed.configureTestingModule({
      providers: [TokenService]
    });
    service = TestBed.get(TokenService);

    let store = {};
    const mockLocalStorage = {
      getItem: (key: string): string => {
        return key in store ? store[key] : null;
      },
      setItem: (key: string, value: string) => {
        store[key] = `${value}`;
      },
      removeItem: (key: string) => {
        delete store[key];
      },
      clear: () => {
        store = {};
      },
      length: () => {
        return Object.keys(store).length;
      }
    };

    spyOn(localStorage, 'getItem')
      .and.callFake(mockLocalStorage.getItem);
    spyOn(localStorage, 'setItem')
      .and.callFake(mockLocalStorage.setItem);
    spyOn(localStorage, 'removeItem')
      .and.callFake(mockLocalStorage.removeItem);
    spyOn(localStorage, 'clear')
      .and.callFake(mockLocalStorage.clear);
    spyOn(localStorage, 'length')
      .and.callFake(mockLocalStorage.length);
  });

  it('should be created',
    () => {
      expect(service).toBeTruthy();
    });

  it('should store the token in localStorage',
    () => {
      service.setAccessToken('sometoken');
      expect(localStorage.getItem('id_token')).toEqual('sometoken');
    });

  it('should return stored token from localStorage',
    () => {
      localStorage.setItem('id_token', 'anothertoken');
      expect(service.getAccessToken()).toEqual('anothertoken');
    });

  it('should return stored token number from localStorage',
    () => {
      localStorage.setItem('id_token-0', 'aiu');
      localStorage.setItem('id_token-1', 'eo');
      localStorage.setItem('id_token-2', 'ka');
      expect(service.getAccessTokenNum).toEqual(3);
    });

  it('mock-length-test',
    () => {
      localStorage.setItem('id_token-0', 'aiu');
      localStorage.setItem('id_token-1', 'eo');
      localStorage.setItem('id_token-2', 'ka');
      expect(localStorage.length).toEqual(3);
    });
});

発生している問題・エラーメッセージ

5 specs, 2 failures
Spec List | Failures
TokenService should return stored token number from localStorage
Expected Function to equal 3.
Error: Expected Function to equal 3.
    at stack (http://localhost:9876/absoluteC:/Users/gsakurai/IdeaProjects/Angular-practice/node_modules/jasmine-core/lib/jasmine-core/jasmine.js?0b1eaf7a13cae32191eadea482cfc96ae41fc22b:2455:17)
    at buildExpectationResult (http://localhost:9876/absoluteC:/Users/gsakurai/IdeaProjects/Angular-practice/node_modules/jasmine-core/lib/jasmine-core/jasmine.js?0b1eaf7a13cae32191eadea482cfc96ae41fc22b:2425:14)
    at Spec.expectationResultFactory (http://localhost:9876/absoluteC:/Users/gsakurai/IdeaProjects/Angular-practice/node_modules/jasmine-core/lib/jasmine-core/jasmine.js?0b1eaf7a13cae32191eadea482cfc96ae41fc22b:901:18)
    at Spec.addExpectationResult (http://localhost:9876/absoluteC:/Users/gsakurai/IdeaProjects/Angular-practice/node_modules/jasmine-core/lib/jasmine-core/jasmine.js?0b1eaf7a13cae32191eadea482cfc96ae41fc22b:524:34)
    at Expectation.addExpectationResult (http://localhost:9876/absoluteC:/Users/gsakurai/IdeaProjects/Angular-practice/node_modules/jasmine-core/lib/jasmine-core/jasmine.js?0b1eaf7a13cae32191eadea482cfc96ae41fc22b:845:21)
    at Expectation.toEqual (http://localhost:9876/absoluteC:/Users/gsakurai/IdeaProjects/Angular-practice/node_modules/jasmine-core/lib/jasmine-core/jasmine.js?0b1eaf7a13cae32191eadea482cfc96ae41fc22b:2369:12)
    at UserContext.<anonymous> (http://localhost:9876/_karma_webpack_/webpack:/src/app/token-service.service.spec.ts:67:41)
    at ZoneDelegate../node_modules/zone.js/dist/zone.js.ZoneDelegate.invoke (http://localhost:9876/_karma_webpack_/webpack:/node_modules/zone.js/dist/zone.js:391:1)
    at ProxyZoneSpec.push../node_modules/zone.js/dist/zone-testing.js.ProxyZoneSpec.onInvoke (http://localhost:9876/_karma_webpack_/webpack:/node_modules/zone.js/dist/zone-testing.js:289:1)
    at ZoneDelegate../node_modules/zone.js/dist/zone.js.ZoneDelegate.invoke (http://localhost:9876/_karma_webpack_/webpack:/node_modules/zone.js/dist/zone.js:390:1)
TokenService mock-length-test
Expected 0 to equal 3.
Error: Expected 0 to equal 3.
    at stack (http://localhost:9876/absoluteC:/Users/gsakurai/IdeaProjects/Angular-practice/node_modules/jasmine-core/lib/jasmine-core/jasmine.js?0b1eaf7a13cae32191eadea482cfc96ae41fc22b:2455:17)
    at buildExpectationResult (http://localhost:9876/absoluteC:/Users/gsakurai/IdeaProjects/Angular-practice/node_modules/jasmine-core/lib/jasmine-core/jasmine.js?0b1eaf7a13cae32191eadea482cfc96ae41fc22b:2425:14)
    at Spec.expectationResultFactory (http://localhost:9876/absoluteC:/Users/gsakurai/IdeaProjects/Angular-practice/node_modules/jasmine-core/lib/jasmine-core/jasmine.js?0b1eaf7a13cae32191eadea482cfc96ae41fc22b:901:18)
    at Spec.addExpectationResult (http://localhost:9876/absoluteC:/Users/gsakurai/IdeaProjects/Angular-practice/node_modules/jasmine-core/lib/jasmine-core/jasmine.js?0b1eaf7a13cae32191eadea482cfc96ae41fc22b:524:34)
    at Expectation.addExpectationResult (http://localhost:9876/absoluteC:/Users/gsakurai/IdeaProjects/Angular-practice/node_modules/jasmine-core/lib/jasmine-core/jasmine.js?0b1eaf7a13cae32191eadea482cfc96ae41fc22b:845:21)
    at Expectation.toEqual (http://localhost:9876/absoluteC:/Users/gsakurai/IdeaProjects/Angular-practice/node_modules/jasmine-core/lib/jasmine-core/jasmine.js?0b1eaf7a13cae32191eadea482cfc96ae41fc22b:2369:12)
    at UserContext.<anonymous> (http://localhost:9876/_karma_webpack_/webpack:/src/app/token-service.service.spec.ts:75:35)
    at ZoneDelegate../node_modules/zone.js/dist/zone.js.ZoneDelegate.invoke (http://localhost:9876/_karma_webpack_/webpack:/node_modules/zone.js/dist/zone.js:391:1)
    at ProxyZoneSpec.push../node_modules/zone.js/dist/zone-testing.js.ProxyZoneSpec.onInvoke (http://localhost:9876/_karma_webpack_/webpack:/node_modules/zone.js/dist/zone-testing.js:289:1)
    at ZoneDelegate../node_modules/zone.js/dist/zone.js.ZoneDelegate.invoke (http://localhost:9876/_karma_webpack_/webpack:/node_modules/zone.j

追記

LocalStorageのlengthはプロパティでした。
なのでspyOnは

    spyOnProperty(localStorage, 'length', 'get').and.returnValue(mockLocalStorage.length());


となるはずでした。
しかし、しかし、setItemで何を入れてもstore{}の数が0から変わりません、なぜでしょうか?

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

0

これでどうでしょう?
getAccessTokenNumという関数を実行してないので
「関数オブジェクト」と「3」を比べてます

expect(service.getAccessTokenNum).toEqual(3);
↓
expect(service.getAccessTokenNum()).toEqual(3);

mock-length-test
こちらはまだよくわかりません。。。
もうすこし調べてみます。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.78%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る