概要
VueRouter のナビゲーションガードのテストの書き方について。
- グローバルガード
- コンポーネント内ガード
それぞれでの書き方を紹介します。
グローバルガード
以下のような beforeEach
フックを定義した router
インスタンスがあるとします。
// router.js
// ...
router.beforeEach((to, next, from) => {
authMiddleware(to, next, from);
});
beforeEach
などのフックは router
インスタンスの中ですべて beforeHooks
という場所へ登録されるようになっています。
登録されているフックを実行したい場合、 beforeHooks
を forEach
で呼び出します。
import router from "@/router";
import { authMiddleware } from "@/auth";
jest.mock("@/auth");
authMiddleware.mockImplementation(jest.fn());
describe("router.js", () => {
test("beforeEach", () => {
const next = jest.fn();
router.beforeHooks.forEach((hook) => {
hook(undefined, undefined, next);
});
expect(authMiddleware).toHaveBeenCalled();
});
});
この方法でもテストは実行できます。
しかし、beforeHooks
に登録されているすべてのフックを呼び出してしまうという欠点があります。
フックを個別に呼び出してテストを実行したい場合は、フック自体をモジュールとして抽出してやると良いでしょう。
// router.js
// ...
export function beforeEach(to, from, next) {
authMiddleware(to, from, next);
}
router.beforeEach((to, from, next) => beforeEach(to, from, next));
この場合のテストは以下のようになります。
モジュールとして抽出したおかげで router
インスタンスを介さずにテストが実行できました。
// beforeEach.spec.js
import { beforeEach } from "@/router";
import { authMiddleware } from "@/auth";
jest.mock("@/auth");
authMiddleware.mockImplementation(jest.fn());
describe("beforeEach hook", () => {
test("call authMiddleware function", () => {
const next = jest.fn();
beforeEach(undefined, undefined, next);
expect(authMiddleware).toHaveBeenCalled();
});
});
コンポーネント内ガード
コンポーネント内ガードの場合、特に難しいことはありません。
import
したコンポーネントから call()
関数を使ってテスト対象を呼び出すだけです。
// HelloWorld.vue
<script>
import { authMiddleware } from "@/auth";
export default {
name: "HelloWorld",
beforeRouteEnter(to, from, next) {
authMiddleware(to, from, next);
},
};
</script>
// HelloWorld.spec.js
import { shallowMount } from "@vue/test-utils";
import HelloWorld from "@/components/HelloWorld.vue";
import { authMiddleware } from "@/auth";
jest.mock("@/auth");
authMiddleware.mockImplementation(jest.fn(() => true));
describe("HelloWorld.vue", () => {
test("beforeRouteEnter", () => {
const wrapper = shallowMount(HelloWorld);
HelloWorld.beforeRouteEnter.call(
wrapper.vm,
undefined,
undefined,
undefined
);
expect(authMiddleware).toHaveBeenCalled();
});
});