...

/

Unit Testing the Survey Results State

Unit Testing the Survey Results State

Let's learn how to perform unit testing on a LiveView component.

We’ll begin with some unit tests that cover the SurveyResultsLive component’s ability to manage survey results data in state. First up is the assign_products_with_average_ratings/2 reducer function, which needs to handle both an empty survey results dataset and one with existing product ratings. First, we’ll make sure the reducer creates the correct socket state when no product ratings exist.

Defining the Test module

We started by defining a test module in pento/test/pento_web/live/survey_results_live_test.exs, like this:

Press + to interact
defmodule PentoWeb.SurveyResultsLiveTest do
use Pento.DataCase
alias PentoWeb.SurveyResultsLive

Note the use Pento.DataCase line. This pulls in the Pento.DataCase behavior that provides access to the ExUnit testing functions and provides our test with a connection to the application’s test database.

We’ll also notice that our module aliases the SurveyResultsLive component. That’s the component we’re testing in this module. We need to perform a few other aliases too. We’ll use them to establish some fixtures and helper functions to simplify the creation of test data, and we defined them in pento/test/pento_web/live/survey_results_live_test.exs like this:

Press + to interact
alias Pento.{Accounts, Survey, Catalog}
@create_product_attrs %{
description: "test description",
name: "Test Game",
sku: 42,
unit_price: 120.5
}
@create_user_attrs %{
email: "test@test.com",
password: "passwordpassword"
}
@create_user2_attrs %{
email: "another-person@email.com",
password: "passwordpassword"
}
@create_demographic_attrs %{
gender: "female",
year_of_birth: DateTime.utc_now.year - 15
}
@create_demographic2_attrs %{
gender: "male",
year_of_birth: DateTime.utc_now.year - 30
}
defp product_fixture do
{:ok, product} = Catalog.create_product(@create_product_attrs)
product
end
defp user_fixture(attrs \\ @create_user_attrs) do
{:ok, user} = Accounts.register_user(attrs)
user
end
defp demographic_fixture(user, attrs \\ @create_demographic_attrs) do
attrs =
attrs
|> Map.merge(%{user_id: user.id})
{:ok, demographic} = Survey.create_demographic(attrs)
demographic
end
defp rating_fixture(stars, user, product) do
{:ok, rating} = Survey.create_rating(%{
stars: stars,
user_id: user.id,
product_id: product.id
})
rating
end
defp create_product(_) do
product = product_fixture()
%{product: product}
end
defp create_user(_) do
user = user_fixture()
%{user: user}
end
defp create_rating(stars, user, product) do
rating = rating_fixture(stars, user, product)
%{rating: rating}
end
defp create_demographic(user) do
demographic = demographic_fixture(user)
%{demographic: demographic}
end
defp create_socket(_) do
%{socket: %Phoenix.LiveView.Socket{}}
end

Test fixtures create test data, and ours use module attributes to create User, Demographic, Product, and Rating records, followed by a few helpers that call on our fixtures and return the newly created records. We’ll see these helper functions, and their return values, in action in a bit.

Now that our test module is defined and we’ve implemented helper functions to create test data, we’re ready to write our very first test. We’ll start with a test that verifies the socket state when there are no product ratings. We add a call to the setup/1 function with the list of helpers that will create a user, product, and socket struct in this file ...