3

我目前正在努力处理混合配置值(特别是在运行测试时)。这是我的场景:

  • 我有一个客户端库,带有一些常见的配置值(密钥、秘密、区域)。
  • 我想测试没有区域值设置时会发生什么
  • 我没有test.exs文件/config

我目前正在这样做(这不起作用)。正在测试的模块(简化):

defmodule Streamex.Client do
  @api_region Application.get_env(:streamex, :region)
  @api_key Application.get_env(:streamex, :key)
  @api_secret Application.get_env(:streamex, :secret)
  @api_version "v1.0"
  @api_url "api.getstream.io/api"

  def full_url(%Request{} = r) do
    url = <<"?api_key=", @api_key :: binary>>
  end
end

测试:

setup_all do
  Streamex.start
  Application.put_env :streamex, :key, "KEY"
  Application.put_env :streamex, :secret, "SECRET"
  Application.put_env :streamex, :secret, ""
end

运行时发生的情况mix test是,从这些值设置属性的主模块抛出以下错误,因为它找不到有效值:

lib/streamex/client.ex:36: invalid literal nil in <<>>

我还在开始,所以这看起来很明显,但是在阅读文档后我找不到解决方案。

4

1 回答 1

5

问题是您将返回值存储Application.get_env在模块属性中,该属性在编译时进行评估。如果您更改测试中的值,它不会反映在模块属性中 - 您将始终获得mix编译该模块时存在的值,其中包括评估config/config.exsmix编译该模块之前编译的所有模块。解决方法是将可以更改的变量移动到函数中,并在使用时调用这些函数:

defmodule Streamex.Client do
  @api_version "v1.0"
  @api_url "api.getstream.io/api"

  def full_url(%Request{} = r) do
    url = <<"?api_key=", api_key :: binary>>
  end

  def api_region, do: Application.get_env(:streamex, :region)
  def api_key, do: Application.get_env(:streamex, :key)
  def api_secret, do: Application.get_env(:streamex, :secret)
end

请注意,如果这是一个库,并且您希望库的用户能够在其配置文件中配置值,则必须在运行时使用函数调用,因为应用程序的依赖项是在应用程序之前编译的。

于 2016-08-01T15:24:59.987 回答