LoginSignup
10
3

More than 1 year has passed since last update.

JestとVue.jsでsetIntervalやsetTimeoutのテストを書く

Last updated at Posted at 2023-02-02

はじめに

setIntervalを使ったポーリングのテストを書こうとした時に、なかなか動くテストを書けずに詰まりました。

テストしたいコード

今回テストしたかったのは、下のようなコードです。
5分ごとにtestFunction()が呼ばれるようになっています。

component.js
const Comp = {
    // ...
    created() {
        setInterval(this.testFunction, 300000);
    },
    // ...
    methods: {
        testFunction() {
            console.log("foo");
        }
    }
}

動いたテストコード

最終的に動いたのは、jest.spyOn()でモック関数を作成する方法でした。

component.test.js
import { expect, describe, test } from "@jest/globals";
import { shallowMount } from "@vue/test-utils";
import Comp from "/.../...";

describe("ポーリング", () => {
    test("ポーリングのメソッドが5分ごとに呼ばれている", () => {
        // testFunction()をspyOnでモックする
        const spyTestFunction = jest.spyOn(Comp.methods, "testFunction");
        // タイマーモックを有効にする
        jest.useFakeTimers();
        // マウント
        shallowMount(Comp);
        // 10分時間を進める
        jest.advanceTimersByTime(600000);
        // 2回呼ばれているか
        expect(spyTestFunction).toHaveBeenCalledTimes(2);
    });
});

各コードのはたらき

まず、jest.spyOn()でモック関数を書いています。
spyOnは、メソッド自体を上書きしているのではなく、テストでもメソッドを呼ぶために名前付けするような働きをしているようです。

const spyTestFunction = jest.spyOn(Comp.methods, "testFunction");

テスト内で時間を自由に操作できるように、フェイクタイマーを有効化します。

jest.useFakeTimers();

ms単位で時間を好きに進めることができます。

jest.advanceTimersByTime(600000);

動かなかったテストコード

動かなかった方もついでに載せておきます。
こちらは、jest.fn ()を使ってモック関数を作り、マウンティングオプションを使ってメソッドを乗っ取ろうとしましたが、うまくいきませんでした。

component.test.js
import { expect, describe, test } from "@jest/globals";
import { shallowMount } from "@vue/test-utils";
import Comp from "/.../...";

describe("ポーリング", () => {
    test("ポーリングのメソッドが5分ごとに呼ばれている", () => {
        jest.useFakeTimers();

        // モック関数を作成してモックしようとしたけど
        const mockTestFunction = jest.fn(() => {});
        
        shallowMount(Comp, {
            // どうやらこれではモックが効かないらしい
            global: {
                mocks: { testFunction: mockTestFunction } 
            }
        }

        jest.advanceTimersByTime(600000);
        expect(spyAjaxFetchNotification).toHaveBeenCalledTimes(2);
    }
}

メソッドはインスタンスではないから、mockとしてかましても動かないのかなと思っています。

終わりに

なんで前者は動いて後者は動いていないのか分かっていません。
jest、奥が深いです。

参考記事

10
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
3