I recently started working with elixir and had the opportunity to create a library at Next Business Solutions called ExOktaAuth that enables elixir applications to handle signup/sign-in flows using Okta's OAuth 2.0/OIDC service.
Now while writing tests for the library, I faced an issue while trying to test a function that was dependent on application configuration that is usually defined in the config.ex file of the phoenix application that is using the library as a dependency.
This is a snippet of the functions code:
config = :ex_okta_auth |> Application.fetch_env!(__MODULE__) |> validate_config!(:client_id) |> validate_config!(:client_secret) |> validate_config!(:site) |> validate_config!(:redirect_uri) site = Keyword.get(config, :site) ExOAuth2.Client.new([ strategy: __MODULE__, client_id: Keyword.get(config, :client_id), client_secret: Keyword.get(config, :client_secret), site: site, redirect_uri: Keyword.get(config, :redirect_uri), authorize_url: site <> "/v1/authorize", token_url: site <> "/v1/token" ]) |> ExOAuth2.Client.put_serializer("application/json", Jason)
Essentially what this code does is load and validate configuration options that it acquires from the application's config.ex file and uses that to create an %ExOAuth2.Client struct that is responsible for setting up the definitions used for interactions with okta's API.
This works all good and well but implementing a unit test for this function turned out to be quite difficult for me since I am new to elixir.
Since the function was dependent on the configuration, I had to find a way to load a specific configuration at runtime so the function could acquire those configuration options during testing.
I came up with the following solution.
Step 1: Define configuration to load during test
Create a file named config.ex in the test/ folder of your library.
import Config config :ex_okta_auth, ExOktaAuth.Okta, client_id: "isoaspoaisa", client_secret: "kajskaljs", site: "http://127.0.0.1:4000/default", redirect_uri: "https://your-apps-callback-uri"
Step 2: Load config dynamically during tests
Config.Reader.read!("test/config.ex") |> Application.put_all_env()
Here you can see how I used this solution in the context of a real test.
defmodule ExOktaAuthTest do use ExUnit.Case doctest ExOktaAuth setup_all do setup_config() {:ok, state: :ok} end def setup_config() do Config.Reader.read!("test/config.ex") |> Application.put_all_env() end test "Should return a valid client" do assert ExOktaAuth.Okta.client == Helpers.valid_client end end
I would love to know if there is a better solution for this problem and if my solution has any pitfalls, so please do critique and provide feedback.
This was a post from Alexandre Juca, A software Engineer working at a wonderful company called Next Solutions based in Luanda/Angola.
Top comments (0)