I get sometimes error in my tests

I have a suite of tests for an API app that uses mongoDB, sometimes all the tests pass but sometimes I get this error.

test index/2 OK (WorkersWeb.Api.V1.CountyControllerTest)
     test/workers_web/controllers/api/v1/county_controller_test.exs:18
     ** (Protocol.UndefinedError) protocol Enumerable not implemented for nil. This protocol is implemented for: DBConnection.PrepareStream, DBConnection.Stream, Date.Range, File.Stream, Function, GenEvent.Stream, HashDict, HashSet, IO.Stream, List, Map, MapSet, Mongo.AggregationCursor, Mongo.Cursor, Mongo.SinglyCursor, Range, Stream
     code: assert Enum.count(json["counties"]) == 3
     stacktrace:
       (elixir) /home/boris/.kiex/builds/elixir-git/lib/elixir/lib/enum.ex:1: Enumerable.impl_for!/1
       (elixir) /home/boris/.kiex/builds/elixir-git/lib/elixir/lib/enum.ex:153: Enumerable.count/1
       (elixir) lib/enum.ex:554: Enum.count/1
       test/workers_web/controllers/api/v1/county_controller_test.exs:27: (test)

The error doesn’t appear in the same place, is this some kind of race condition error where the tests is done before mongo creates the item to be tested?

Can you please show the test? Whatever you are doing is expecting a list by the looks of it, but in this case json["counties"] is returning nil, which is why you get the protocol error.

This is the test for this case

defmodule WorkersWeb.Api.V1.CountyControllerTest do
  use WorkersWeb.ConnCase
  alias Workers.Mongo, as: Wmongo
  @token "authtoken123"

  setup do
    Wmongo.delete_many!("counties", %{})

    conn = build_conn()
    |> put_req_header("accept", "application/json")
    |> put_req_header("content-type", "text/json")

    jwt = sign_and_store_user(@token)
    {:ok, conn: conn, jwt: jwt}
  end

  describe "index/2" do
    test "OK", %{conn: conn, jwt: jwt} do
      create_counties()

      conn = conn
      |> put_req_header("authorization", jwt)
      |> get("/api/v1/counties?order_by=name&order_dir=desc")

      json = Poison.decode!(conn.resp_body)

      assert Enum.count(json["counties"]) == 3
      assert Enum.map(json["counties"], &(&1["name"])) == ["Sheridan", "SABINE PASS", "SABINE OTHER"]

      co = List.first(json["counties"])
      assert Map.keys(co) == ["api_id", "name", "state_abbr"]
    end

    test "Unathorized", %{conn: conn} do
      conn = get(conn, "/api/v1/counties")

      assert conn.status == 401
      json = Poison.decode!(conn.resp_body)

      assert json["msg"] == "Please login."
    end
  end

  describe "show/2" do
    test "ok", %{conn: conn, jwt: jwt} do
      api_id = "49-033"
      Wmongo.insert_one!("counties", %{name: "Sheridan", county_api: "033", api_id: api_id, state_abbr: "WY"})

      conn = conn
      |> put_req_header("authorization", jwt)
      |> get("/api/v1/counties/#{api_id}")

      json = Poison.decode!(conn.resp_body)
      assert json["county"] == %{"api_id" => "49-033", "name" => "Sheridan", "state_abbr" => "WY"}
    end

    test "Not found", %{conn: conn, jwt: jwt} do
      conn = conn
      |> put_req_header("authorization", jwt)
      |> get("/api/v1/counties/49-333")
      json = Poison.decode!(conn.resp_body)

      assert json["error"] == "County not found"
      assert conn.status == 404
    end
  end
end

Method to create counties

  def create_counties do
    Mongo.delete_many(:mongo, "counties", %{}, [pool: DBConnection.Poolboy])
    Mongo.insert_many(:mongo, "counties", load_fixture("counties")["counties"], [pool: DBConnection.Poolboy])
  end

Please check I get sometimes error in my tests

A couple things I’m seeing.

You are using Mongo.insert_many/4 to insert your records. Try using Mongo.insert_many!/4. This will raise an error if for whatever reason the insert fails. Right now, it will just fail silently (because it currently returns {:error, reason}.

Your WorkersWeb.ConnCase module, does it use async: true by default? If so, that can cause an issue since you are not using unique collection names.

2 Likes