@kintone/rest-api-clientをモックする
副業先でkintoneを利用している。kintoneの機能だけでは賄えない部分は、JSカスタマイズを作成し補っている。そのJSカスタマイズを作成するときに@kintone/rest-api-clientを使うことが多く、単体テスト時はそれをモックしてテストする。今回は備忘録的に@kintone/rest-api-clientをモックする方法について、書く。
インスタンスは外から渡す
モックする方法について書く前に、モックしやすいインタフェースについて書く。
以下のように、関数内でKintoneRestAPIClientをインスタンス化するとテストしづらい。jest.mockはクラスでもモックできるが、KintoneRestAPIClientはclient.record.getRecord(...)のようにプロパティを挟んでメソッドが生えているのでうまくモックされない。
const someFunction = () => {
const client = new KintoneRestAPIClient();
…
}
なので、インスタンスは外から渡す形に変える。JSカスタマイズのようにブラウザ上でKintoneRestAPIClientを使う場合、コンストラクタに何も渡す必要がないので、デフォルト引数でインスタンス化したKintoneRestAPIClientを渡すように書けばよい。そうすると、その関数を利用するときにはKintoneRestAPIClientを意識する必要はないので、おすすめ。
interface SomeFunctionOptions {
client: KintoneRestAPIClient;
}
const someFunction = ({
client = new KintoneRestAPIClient(),
}: SomeFunctionOptions) => {
…
};
// デフォルト引数でインスタンス化しているので、
// 利用するときにインスタンス化して渡す必要はない
someFunction({});
jest.spyOnでモックする
注:jest前提なので、それ以外のテストフレームワークを使っている場合は同じような関数で読み替えてください
まず、テスト用にKintoneRestAPIClientをインスタンス化する。jest上でKintoneRestAPIClientを使う場合、Node環境になるので、baseUrl・authをコンストラクタで渡す必要がある。が、モックすればその辺のパラメタはあまり関係なくなるので、適当な値を渡せばOK。
// jestはNode環境なので、
// コンストラクタに色々渡す必要がある
// baseUrl、authが必須になるが、どうせモックするので適当な値でOK
const client = new KintoneRestAPIClient({
baseUrl: "https://example.cybozu.com/k",
auth: {
username: "hoge",
password: "hoge",
},
});
次に、モックしたいメソッドだけjest.spyOnでモックする。TypeScript環境の場合、返り値の型など効くようになって、便利だった気がする。直後にbeforeEachを定義してmockClearしておくと、mockClear忘れでテストが不安定になるのを防ぐことができるので、安心。
// モックしたいメソッドだけjest.spyOnする
const getRecordsMock = jest.spyOn(client.record, 'getRecords');
// beforeEachでmockClearする
beforeEach(() => {
getRecordsMock.mockClear();
});
あとは、mockResolvedValueやmockRejectedValueで返り値をテストしたい形に書き換えたり、expect(mock).toHaveBeenCalledWithなどで想定通りに呼んでいるかをテストすればよい。
test('…', async () => {
getRecordsMock.mockResolvedValue({
records: [],
totalCount: "0"
});
await someFunction({ client });
expect(getRecordsMock).toHaveBeenCalledWith({ … });
});
おわり
JSカスタマイズでもテスト書いていきの気持ちでやっていこうな。