1
Help us understand the problem. What are the problem?

More than 1 year has passed since last update.

posted at

Organization

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

開発時とデプロイ時で関数の定義を変えたいときがある。以下のように書けば、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 で戻してやるのも忘れずに。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Sign upLogin
1
Help us understand the problem. What are the problem?