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)