Fl4m3Ph03n1x

Fl4m3Ph03n1x

Mock is crashing process in umbella project

Background

I have an umbrella project, where I run mix test from the root.
In one of the apps, I am mocking the File module using the Mock library.

Problem

The issue here is that when I run mix test the process dies, with no error message to show:

Manager.Impl.Store.ReaderTest [test/unit/store/reader_test.exs]
  * test list_syndicates/1 returns the list of all known syndicates [L#496]** (EXIT from #PID<0.98.0>) killed

Code

The code of the test is as follows:

defmodule Manager.Impl.Store.ReaderTest do
  use ExUnit.Case, async: false

  alias Manager.Impl.Store.Reader

  import Mock

  setup do
    %{
      file_io: File,
      paths: [syndicates: ["syndicates.json"]]
    }
  end

  describe "lists syndicates" do
    test_with_mock "returns the list of all known syndicates", %{paths: paths} = deps, File, [],
      read: fn _filename -> {:ok, "[\"utc\"]"} end do
      # Act
      actual = Reader.list_syndicates(deps)

      expected = {:ok, [%Syndicate{name: "UTC", id: :utc, catalog: []}]}

      expected_path = Path.join(paths[:syndicates])

      # Assert
      assert actual == expected
      assert_called(File.read(expected_path))
    end
  end
end

In comparison, the follow test (which does not use mock) works just fine:

defmodule Manager.Impl.Store.ReaderTest do
  @moduledoc false

  use ExUnit.Case, async: false

  alias Manager.Impl.Store.Reader

  import Mock

  setup do
    %{
      paths: [syndicates: ["syndicates.json"]]
    }
  end

  describe "list_syndicates/1" do
    defmodule FileMockListSyndicates do
      @moduledoc false

      def read(path) do
        assert path == "syndicates.json"
        {:ok, "[\"utc\"]"}
      end
    end

    setup do
      %{
        file_io: Manager.Impl.Store.ReaderTest.FileMockListSyndicates
      }
    end

    test "returns the list of all known syndicates",
         %{paths: paths} = deps do
      # Act
      actual = FileSystem.list_syndicates(deps)
      expected = {:ok, [%Syndicate{name: "UTC", id: :utc, catalog: []}]}

      # Assert
      assert actual == expected
    end
  end
end

To me this is rather surprising. One alternative crashes the process with no error message, while the other makes everything work.

To me, this indicates one of three problems:

  1. A problem with the library Mock
  2. A problem with my setup of the library
  3. A problem with the test that causes the process to crash

I believe the second and third options to be the most probable, but without any information about the error, I can’t be sure. The process simply dies.

Question

Why is my process dying, and how can I fix it?

Marked As Solved

Fl4m3Ph03n1x

Fl4m3Ph03n1x

Mock depends on :meck, which does swap out the complete module
within the runtime – as in make the VM unload the existing module and
load the module with the mock code. (…) The best improvement to get
would be better errors or disclaimers.

Source: Mock is crashing process in umbella project - #4 by LostKobrakai - Questions / Help - Elixir Programming Language Forum

At the time of this writing, I have tested all major mocking libraries (Mock, Mox and Mimic).
Both Mock and Mimic rely on :meck underneath. Rather surprisingly, I get the exact same issue with Mimic as I got with Mock, i.e., the process crashes without warning.

This leaves me to the only logical conclusion, which is that the problem I am facing is related to the underlying system that servers as a base for both libraries: :meck. This issue does not happen using Mox.

I have therefore decided not to use Mock (nor Mimic) for the application and I am instead injecting the dependencies directly into the functions that need them. This last approach is very lightweight and does allow for async: true which gives a noticeable speed increase when running mix test.

Because I am only using a very small portion of the external system’s API (2 - 3 functions) this fits well with my needs. However, If I were to use all functions from said API (let’s say 20) this solution would be rather difficult to manage.

I don’t expect the affected modules to evolve in such a direction, so for the time being, I am rather happy.

Here is a sample test for those searching for inspiration (using File as an example):

setup do
  %{
    paths: [products: ["products.json"]]
  }
end

test "returns list of available products from given syndicate", %{paths: paths} = deps do
  read_fn = fn filename ->
    assert filename == Path.join(paths[:products])

    {:ok, "[{\"name\": \"utc\"}]"}
  end

  deps = Map.put(deps, :io, %{read: read_fn})
  syndicate = Syndicate.new(name: "UTC", id: :utc)

  assert FileSystem.list_products(syndicate, deps) ==
           {:ok, [Product.new(%{"name" => "Bananas"})]}
end

Where Next?

Popular Backend topics Top

pillaiindu
Cross posting from HashNode. A friend of mine is creating Uber-like app for a small company with 200 to 1000 cars. The app will operate ...
New
AstonJ
Just done a fresh install of macOS Big Sur and on installing Erlang I am getting: asdf install erlang 23.1.2 Configure failed. checking ...
New
gagan7995
API 4 Path: /user/following/ Method: GET Description: Returns the list of all names of people whom the user follows Response [ { ...
New
Fl4m3Ph03n1x
Background I am trying to get a Github Action working with Windows and Bakeware because I am trying to create a release using it. Howeve...
New
JimmyCarterSon
Hello, I am working on a new application with Elixir, Dish_out. I want to see Data I follow this tutorial with Elixir Casts. However, I ...
New
sona11
In Java, if I try to do.equals() on a null string, a null pointer error is issued. I’m wondering whether I can perform the following if I...
New
sona11
If isReachable throws an IOException in Java, what is the right step to do and why? The application, I believe, should halt the process ...
New
pillaiindu
Currently reading the book “Programming Phoenix LiveView”. At the end of the Chapter 1, I’m trying to solve the guess game. If the user ...
New
ogoldberg
Any recommendations on good resources for learning Elixir, Phoenix, and Ash?
New
Patricia-Mendes13
Hi guys!! I´m studying and got a Full stack course but the course lacked a lot of support and and info to learn as it´s a course after wo...
New

Other popular topics Top

DevotionGeo
I know that -t flag is used along with -i flag for getting an interactive shell. But I cannot digest what the man page for docker run com...
New
AstonJ
Curious to know which languages and frameworks you’re all thinking about learning next :upside_down_face: Perhaps if there’s enough peop...
New
PragmaticBookshelf
From finance to artificial intelligence, genetic algorithms are a powerful tool with a wide array of applications. But you don't need an ...
New
AstonJ
I ended up cancelling my Moonlander order as I think it’s just going to be a bit too bulky for me. I think the Planck and the Preonic (o...
New
AstonJ
In case anyone else is wondering why Ruby 3 doesn’t show when you do asdf list-all ruby :man_facepalming: do this first: asdf plugin-upd...
New
rustkas
Intensively researching Erlang books and additional resources on it, I have found that the topic of using Regular Expressions is either c...
New
PragmaticBookshelf
Develop, deploy, and debug BEAM applications using BEAMOps: a new paradigm that focuses on scalability, fault tolerance, and owning each ...
New
CommunityNews
A Brief Review of the Minisforum V3 AMD Tablet. Update: I have created an awesome-minisforum-v3 GitHub repository to list information fo...
New
AstonJ
This is a very quick guide, you just need to: Download LM Studio: https://lmstudio.ai/ Click on search Type DeepSeek, then select the o...
New
PragmaticBookshelf
Fight complexity and reclaim the original spirit of agility by learning to simplify how you develop software. The result: a more humane a...
New