samedi 16 décembre 2017

Testing Elixir/Phoenix Service modules

I've been playing around with Elixir/Phoenix third party modules. ( Modules that are used to fetch some data from a 3rd party serice ) One of those module looking like so:

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

The actual data doesn't matter in my question. So now, I'm interested in how can I dynamically configure the @twitter_url module variable in tests to make some of the tests fail on purpose. For example:

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

How can I achieve this? Note: I know I can use :configs to configure @twiter_url separately in dev and test environments, but I'd like to be able to test on real response from the twitter API too, and that would change the URL on the entire Test environment.
One of the solutions that I came up with was

def fetch_tweets(user, opts \\ []) do
  _fetch_tweets(user, opts[:fail] || false)
end

defp _fetch_tweets(user, [fail: true]) do
  # Fails
end

defp _fetch_tweets(user, [fail: false]) do
  # Normal fetching
end

But that just seems hackish and silly, there must be a better solution to this.

Aucun commentaire:

Enregistrer un commentaire