Fixing broken poll tests

If we run the mix test as it is it will fail, but that's okay as it's actually our expected behavior. As we have just added a new requirement of user_id for the creation of all polls, we should expect all of our previous poll creation logic to fail without a user ID as part of the changeset. We'll tackle the failing tests in test/vocial/votes/votes_test.exs, which will involve a lot of code-but not a lot of complicated code.

First, we need to add some code to the top of our Vocial.VotesTest module, which creates a user that we can use as the user ID value for all future polls. As mentioned in the last chapter, ExUnit provides a very simple way for us to set those features up, via the setup function. So, we'll now create a setup function that will return out :ok and a pre-created user for us to use:

  setup do
{:ok, user} = Vocial.Accounts.create_user(%{
username: "test",
email: "[email protected]",
password: "test",
password_confirmation: "test"
})
{:ok, user: user}
end

Remember that every setup function that we write into our tests needs to send out :ok as part of the tuple as well as anything we want to be returned as part of the second value. In our case, we'll use a keyword list where the only initial key in it is :user, which will store the newly-created user from the account's context. Next, we start modifying each of the tests, starting at the top; list_polls() needs to account for the new user and user ID values before the user is created in order to verify the results:

    test "list_polls/0 returns all polls", %{user: user} do
poll = poll_fixture(%{user_id: user.id})
assert Votes.list_polls() == [poll]
end

After adding a description of the test, we add a pattern match statement to catch the user key returned as part of the setup function. Then, in our poll_fixture function call, we add an additional set of parameters that includes user_id. This will pass user_id to the changeset and will verify that a poll has been associated with the right user on creation. Next, we'll need to scroll down to our creation tests and make those pass, following essentially the same patterns as previously:

    test "create_poll/1 returns a new poll", %{user: user} do
{:ok, poll} = Votes.create_poll(Map.put(@valid_attrs, :user_id, user.id))
assert Enum.any?(Votes.list_polls(), fn p -> p.id == poll.id end)
end

Again, we catch the user. As we're not using the fixture in this particular function (because we want to specifically test the create function in isolation), we're just going to call Map.put3 to return a modified version of the creation hash that includes both the values from @valid_attrs and user_id. Now we need to modify the next few create_poll_with_options tests, as follows:

    test "create_poll_with_options/2 returns a new poll with options", %{user: user} do
title = "Poll With Options"
options = ["Choice 1", "Choice 2", "Choice 3"]
{:ok, poll} = Votes.create_poll_with_options(%{title: title, user_id: user.id}, options)
assert poll.title == title
assert Enum.count(poll.options) == 3
end

We'll also need to modify the next test, even if it's currently passing. We do this to keep the semantics of the test clear, as shown in the following snippet:

    test "create_poll_with_options/2 does not create the poll or options with bad data", %{user: user} do
title = "Bad Poll"
options = ["Choice 1", nil, "Choice 3"]
{status, _} = Votes.create_poll_with_options(%{title: title, user_id: user.id}, options)
assert status == :error
assert !Enum.any?(Votes.list_polls(), fn p -> p.title == "Bad Poll" end)
end

Finally, we need to pop over into the describe block for options, as there is a create test there that can also fail without modifications:

  describe "options" do
test "create_option/1 creates an option on a poll", %{user: user} do
with {:ok, poll} = Votes.create_poll(%{ title: "Sample Poll", user_id: user.id }),
{:ok, option} = Votes.create_option(%{ title: "Sample Choice", votes: 0, poll_id: poll.id }),
option <- Repo.preload(option, :poll)
do
assert Votes.list_options() == [option]
end
end
end

As I said, we've covered a lot of code, but not a lot of complicated code. This will be a pretty common feature as we continue to run through and implement Elixir projects. But don't worry, the simplicity of Elixir allows you to spend more time actually designing the system you want instead of considering every potential failure in it.

Since the test suite is passing (although not the entire test), we now need to hook up the controllers to be able to use the logic as well. Let's move on now that our foundation is secure!

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset