LoginSignup
1

More than 3 years have passed since last update.

関数定義を Mix.env に応じて分ける方法とテスト

Posted at

開発時とデプロイ時で関数の定義を変えたいときがある。以下のように書けば、Mix.env の値に応じて、異なる関数がコンパイルされる。

defmodule MyModule do
  @moduledoc false

  if Mix.env() == :prod do
    @foo Application.fetch_env!(:myapp, :foo)
    def foo, do: @foo
  else
    def foo, do: Application.fetch_env!(:myapp, :foo)
  end
end

リリース時に Mix モジュールは存在しないが、この場合、コンパイル時に使われるだけなので問題ない。ただ、このままだとテスト時には片方の実装しかテストされないので、両方をテストしておきたいところ。以下のようにした。

defmodule MyModuleTest do
  use ExUnit.Case

  import ExUnit.CaptureIO

  @source_filepath __DIR__
                   |> Path.join("../../lib/myapp/my_module.ex")
                   |> Path.expand()
  test "foo" do
    on_exit(fn ->
      Mix.env(:test)
    end)

    # suppress warnings
    capture_io(:stderr, fn ->
      Mix.env(:prod)
      Code.compile_file(@source_filepath)
      assert MyModule.foo(), "compile on Mix.env(:prod)"

      Mix.env(:test)
      Code.compile_file(@source_filepath)
      assert MyModule.foo(), "compile on Mix.env(:test)"
    end)
  end
end

Mix.env を変更してから Code.compile_file/2 で対象ファイルを再コンパイルしてやる。on_exit/2 で戻してやるのも忘れずに。

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
1