[英]Testing Elixir/Phoenix Service modules
我一直在玩Elixir / Phoenix第三方模塊。 (用於從第三方服務獲取某些數據的模塊)這些模塊之一如下所示:
module TwitterService do
@twitter_url "https://api.twitter.com/1.1"
def fetch_tweets(user) do
# The actual code to fetch tweets
HTTPoison.get(@twitter_url)
|> process_response
end
def process_response({:ok, resp}) do
{:ok, Poison.decode! resp}
end
def process_response(_fail), do: {:ok, []}
end
實際數據對我的問題無關緊要。 因此,現在,我對如何在測試中動態配置@twitter_url
模塊變量感興趣,以使某些測試故意失敗。 例如:
module TwitterServiceTest
test "Module returns {:ok, []} when Twitter API isn't available"
# I'd like this to be possible ( coming from the world of Rails )
TwitterService.configure(:twitter_url, "new_value") # This line isn't possible
# Now the TwiterService shouldn't get anything from the url
tweets = TwitterService.fetch_tweets("test")
assert {:ok, []} = tweets
end
end
我該如何實現? 注意:我知道我可以在dev
和test
環境中使用:configs
分別配置@twiter_url
,但是我也希望能夠對Twitter API的真實響應進行測試,這將更改整個測試的URL。環境。
我想到的解決方案之一是
def fetch_tweets(user, opts \\ []) do
_fetch_tweets(user, opts[:fail_on_test] || false)
end
defp _fetch_tweets(user, [fail_on_test: true]) do
# Fails
end
defp _fetch_tweets(user, [fail_on_test: false]) do
# Normal fetching
end
但這似乎有點駭人聽聞和愚蠢,必須對此有一個更好的解決方案。
正如Jose在Mocks And Explicit Contracts中建議的那樣,最好的方法可能是使用依賴項注入:
module TwitterService do
@twitter_url "https://api.twitter.com/1.1"
def fetch_tweets(user, service_url \\ @twitter_url) do
# The actual code to fetch tweets
service_url
|> HTTPoison.get()
|> process_response
end
...
end
現在在測試中,您僅在必要時注入另一個依賴項:
# to test against real service
fetch_tweets(user)
# to test against mocked service
fetch_tweets(user, SOME_MOCK_URL)
這種方法還將使將來更容易插入其他服務。 假定服務遵循某種約定(在這種特殊情況下,給定url的json響應),則處理器的實現不應依賴於其基礎服務。
config
聽起來這里是個好方法。 您可以在運行時在測試中修改配置中的值,然后在測試后將其還原。
首先,在您的實際代碼中,而不是@twitter_url
,請使用Application.get_env(:my_app, :twitter_url)
。
然后,在測試中,可以使用如下包裝函數:
def with_twitter_url(new_twitter_url, func) do
old_twitter_url = Application.get_env(:my_app, :twitter_url)
Application.set_env(:my_app, :twitter_url, new_twitter_url)
func.()
Application.set_env(:my_app, :twitter_url, old_twitter_url)
end
現在在您的測試中,執行以下操作:
with_twitter_url "<new url>", fn ->
# All calls to your module here will use the new url.
end
確保您沒有為此使用異步測試,因為此技術會修改全局環境。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.