時間に依存する機能を持つアプリケーションのテストは、しばしば複雑で時間を要する作業です。「24時間後にログアウトしていること」といったテストのために1日待つのは辛いものがありますね…。
システムの時計を変更することなく、特定の日時でコードが正しく動作するかをテストする方法はないでしょうか。
ここでは、libfaketime
を利用してNode.jsのアプリケーションで時間を自由に操る方法をご紹介します。
libfaketimeとは
libfaketime
は、プロセスに報告される現在日時をマシンのシステムクロックとは異なる値に偽装することを可能にするライブラリです。これは、システムコールに介入し、ユーザーが定義した日時を返すことで実現します。システム全体の日付を変更せずに、特定のプロセスだけのシステム日付を変更することが可能です。テスト環境で時間を操作し、特定の時点でのアプリケーションの動作を確認するのに非常に便利です。
Dockerを使用したlibfaketimeのインストール
Node.jsのアプリケーションでlibfaketime
を使用するには、まずDockerイメージに組み込む必要があります。以下はlibfaketime
をAlpine LinuxベースのNode.jsイメージに組み込むためのDockerfile
の例です。
# libfaketimeをビルドするためのステップ
FROM alpine:3.18 AS builder
RUN apk add build-base git
RUN git clone --depth 1 --branch v0.9.10 https://github.com/wolfcw/libfaketime /usr/local/src/libfaketime
WORKDIR /usr/local/src/libfaketime
RUN make && make install
# Node.jsイメージの準備
FROM node:21-alpine
COPY --from=builder /usr/local/lib/faketime/libfaketimeMT.so.1 /lib/faketime.so
ENV LD_PRELOAD=/lib/faketime.so
ENTRYPOINT ["node", "-e"]
CMD ["console.log(new Date())"]
このDockerfile
では、最初にlibfaketime
のビルドを行い、その後、ビルドしたライブラリをNode.jsのイメージにコピーしています。LD_PRELOAD
環境変数を設定することで、Node.jsプロセスがlibfaketime
を使用するようになります。
Dockerイメージのビルド
以下のコマンドを実行して、先ほどのDockerfile
からDockerイメージをビルドします。
docker build . -t fakedemo
現在日時を改ざんしてみた
ビルドしたDockerイメージを使用して、時間を操作しながらNode.jsアプリケーションを実行できます。
以下のコマンドは、システムの現在時刻から1年後の日時に改ざんした状況を作り、そのうえで毎秒現在時刻をコンソールに出力しますJavaScriptを実行します。
docker run --rm -it -e FAKETIME=+1y fakedemo 'setInterval(() => console.log(new Date()), 1000);'
出力例(実行日が2024年3月21日の場合):
2025-03-21T01:02:15.882Z
2025-03-21T01:02:16.883Z
2025-03-21T01:02:17.885Z
2025-03-21T01:02:18.886Z
上の結果を見てみると、+1y
が作用して日時が1年後になっています。秒数は進んでいることから、+1y
のような指定にすることで日時は固定せず現在のものを使えることが分かります。
日時の指定は絶対時刻(常に固定)や相対時刻(始まりだけ指定)といった様々な指定ができます。詳しくはドキュメントをご覧ください。
libfaketime
を活用することで、時間に依存する複雑なテストも、より簡単かつ正確に実施することができるようになります。