16
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

ElixirAdvent Calendar 2023

Day 20

【Elixirテストの効率化】スタブをMimicで簡単に実装する

Last updated at Posted at 2023-12-19

この記事は Elixir Advent Calendar 2023 シリーズ2 20日目の記事です。

TL;DR

Elixir のテストで爆速にスタブを書きたかったら、Hex のライブラリ Mimic を使うとよいです。

概要

テストはソフトウェア開発において重要な役割を果たしますが、外部依存関係や API の呼び出しによって複雑化することがあったりします。
Elixir のエコシステムでは、これらの課題を解決する選択肢の1つに Mimic というライブラリがあります。

この記事では、Mimic を使用して Elixir のテストでスタブを簡単に実装する方法を紹介します。

Mimic とは?

Mimic は、Elixir のテスト実行中に外部モジュールの関数呼び出しをオーバーライドする ためのライブラリです。
Mimic を使用すると、テスト中に特定の関数が返すべき値を簡単に制御できるようになります。これにより、外部APIの呼び出しやその他の外部依存関係をスタブすることが可能になります。

なお、Mimic の作者 edgurgel さんは、他にも HTTPoison などの各種 Elixir ライブラリを開発されてる方です。

実行環境

  • Elixir 1.15.7 (compiled with Erlang/OTP 26)
  • Phoenix v1.7

セットアップ

Mimicをプロジェクトに追加するには、mix.exs に以下の依存関係を追加し、mix deps.get を実行して依存関係をインストールします。

mix.exs
  defp deps do
    [
      ... ,
      {:mimic, "~> 1.7", only: :test}
    ]
  end

今回の使用例では Timex を test_helper.exs に追記してスタブできるようにします。
(別途 Timex ライブラリの追加 → mix deps.get も必要)

test/test_helper.exs
Mimic.copy(Timex)  # <- add

ExUnit.start()

スタブの実装

Mimic を使用したスタブの実装例として、Timex.now 関数のふるまいをスタブ化する手順を示します。

サンプルコードは、現在の日時 を取得しYYYY-MM-DD形式の文字列にして返すメソッドです。

lib/sample_app/datetime_processor.ex
defmodule SampleApp.DatetimeProcessor do
  @spec get_current_date_string() :: String.t()
  def get_current_date_string() do
    Timex.format!(get_current_datetime(), "{YYYY}-{0M}-{0D}")
  end

  defp get_current_datetime() do
    Timex.now("Asia/Tokyo")
  end
end

これに対するテストを書きたいとします。

test/sample_app/datetime_processor/get_current_date_string_test.exs
defmodule SampleApp.DatetimeProcessor.GetCurrentDateStringTest do
  use ExUnit.Case
  use Mimic

  test "Get current datetime and return the YYYY-MM-DD formatted date string." do
    stub(
      Timex,
      :now,
      fn "Asia/Tokyo" -> DateTime.from_naive!(~N[2024-01-01 12:00:00], "Asia/Tokyo") end
    )

    assert SampleApp.DatetimeProcessor.get_current_date_string() == "2024-01-01"
  end
end

ここでは、Mimic.stub によって Timex.now"Asia/Tokyo" タイムゾーンで呼ばれた際に固定の日時を返すよう設定しています。

たったのこれだけで、テストがその関数の実際の実行に依存することなく、任意の結果を返すことができるようになります。

おわりに

Mimic は、外部依存関係のあるテストを書く際の複雑さを減らすための強力なツールです。
中長期的な観点を踏まえれば Mox が技術選択肢に上がってきますが、規模の小さいプロダクトや検証段階において初速を出してまず動くものを作りたいようなケースでは Mimic はとても有用です。

Mimic.reject みたいな便利なメソッドも揃っているし、Mimic、何より名前がよいので(大事)、Elixir プロジェクトのテスト戦略に Mimic の活用をぜひ検討してみてください。

16
1
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
16
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?