模拟正在伞式项目中崩溃进程

问题描述 投票:0回答:1

背景

我有一个伞式项目,我从根运行

mix test
。 在其中一个应用程序中,我使用 Mock 库模拟 File 模块。

问题

这里的问题是,当我运行

mix test
时,进程终止,没有显示错误消息:

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

代码

测试的代码如下:

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

相比之下,以下测试(不使用模拟)效果很好:

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

对我来说,这相当令人惊讶。一种替代方案会导致进程崩溃且没有错误消息,而另一种方案则可以使一切正常工作。

对我来说,这表明了三个问题之一:

  1. 库 Mock 的问题
  2. 我的库设置有问题
  3. 测试出现问题导致进程崩溃

我相信第二个和第三个选项是最有可能的,但没有任何有关错误的信息,我无法确定。这个进程就直接死掉了。

问题

为什么我的进程死掉了,我该如何修复它?

testing mocking elixir meck
1个回答
0
投票

当您以这种方式模拟模块时,只允许调用

File.read/1
。如果您的代码在任何地方调用
File
模块中的另一个函数,它将失败。要更改此行为,您可以使用 :passthrough 选项。

此外,出于这个原因,模拟标准库函数并不是一个好主意,因为你永远不知道它们在哪里被调用。您可以将

File.read/1
调用包装在另一个函数中,并模拟此函数。

© www.soinside.com 2019 - 2024. All rights reserved.