目標
jestでの単体テスト時にテスト対象クラスの依存先クラスをモックする。
環境
vue-cli 3.2.3
vue createでのプロジェクト作成時にTypeScript、単体テストフレームワークにjestを指定する。
テスト対象
例として下記のようにユーザ情報を取得するリポジトリクラスとリポジトリクラスを利用するサービスクラスを作成する。
リポジトリクラス
UserRepository.ts
export default class UserRepository {
// 指定されたユーザIDのユーザ名を返す
public async getUserName(userId: string): Promise<string> {
// 本来はここでWeb APIを実行するなどしてユーザ情報を取得して返す。
return "";
}
}
サービスクラス
UserService.ts
import UserRepository from "./UserRepository";
export default class UserService {
private userRepository = new UserRepository();
// リポジトリクラスで取得したユーザ名に"Hello "をつけて返す
public async helloUser(userId: string): Promise<string> {
const userName = await this.userRepository.getUserName(userId);
return "Hello " + userName;
}
}
サービスクラスの単体テストを行うために、リポジトリクラスをモック化する。今回の例のようにインスタンス化して利用しているクラスをモック化するには、ドキュメントにあるようにコンストラクタ関数をモックする必要がある。
https://jestjs.io/docs/ja/es6-class-mocks
テストクラスを以下のように作成する。jest.mockを使用しUserServiceの依存先であるUserRepositoryをモック化する。そしてjest.fnを使用しコンストラクタ関数をモック化する。
test.spec.ts
import UserService from "@/UserService";
// モック化処理
jest.mock("@/repositories/UserRepository", () => {
return jest.fn().mockImplementation(() => {
return {
// getUserName関数が返す値を引数userIdの値によらず、"hoge"に固定する
getUserName: async (userId: string): Promise<string> => {
return Promise.resolve("hoge");
}
};
});
});
// テスト
describe("Test", () => {
// 非同期処理のテストのためasyncをつけている
it("helloUser test", async () => {
const service = new UserService();
// helloUser関数の返り値を検査
expect(await service.helloUser("id1")).toEqual("Hello hoge");
});
});