edgurgel / mimic Goto Github PK
View Code? Open in Web Editor NEWA mocking library for Elixir
Home Page: https://hexdocs.pm/mimic
License: Apache License 2.0
A mocking library for Elixir
Home Page: https://hexdocs.pm/mimic
License: Apache License 2.0
Hey my dude.
When attempting to copy a module which contains @dialyzer {:nowarn_function, [&Cachex.get/2, &Cachex.put/4]}
I get the following compilation error:
** (CaseClauseError) no case clause matching: {:error, [{'lib/core_gateway/session/cache.ex', [{1, :erl_lint, {:bad_dialyzer_attribute, {:nowarn_function, &Cachex.get/2}}}, {1, :erl_lint, {:bad_dialyzer_attribute, {:nowarn_function, &Cachex.put/4}}}]}], []}
(mimic 1.5.0) lib/mimic/module.ex:43: Mimic.Module.rename_module/2
(mimic 1.5.0) lib/mimic/module.ex:27: Mimic.Module.replace!/1
(mimic 1.5.0) lib/mimic.ex:344: Mimic.copy/1
test/test_helper.exs:4: (file)
Which is super weird because the attribute is valid and works when compiling normally. Whether or not I should be opening a PR to fix Cachex's typespecs is beyond the scope of this issue ๐
Hope you're well.
James.
When I use Mimic with code coverage tool for ex excoverall
or coverex
Mimic.copy impact to coverage behavior that make coverage ignores and does not track modules which have been Mimic copied.
Please see Calculator module before and after calling Mimic.copy(Coverage.Calculator)
https://github.com/kaorism/coverage-mimic
Thanks!
It's late, so I haven't crafted a reproducer, but I renamed a module that was being stubbed elsewhere in my code and didn't change it there. Then a bunch of tests failed saying that other completely unrelated modules hadn't been copied, when they definitely had. Other times the Mimic genserver crashed outright.
Hi, I'm having an issue running my test suite from the root of my umbrella app. Here's the error:
11:25:03.762 [error] Task #PID<0.1852.0> started from Mimic.Server terminating
** (MatchError) no match of right hand side value: {:error, {:cant_open_file, '/apps/app_1/Elixir.App1-566835.coverdata', :enoent}}
(mimic 1.7.1) lib/mimic/cover.ex:32: Mimic.Cover.replace_coverdata!/3
(elixir 1.13.3) lib/task/supervised.ex:89: Task.Supervised.invoke_mfa/2
(elixir 1.13.3) lib/task/supervised.ex:34: Task.Supervised.reply/4
(stdlib 3.17.1) proc_lib.erl:226: :proc_lib.init_p_do_apply/3
Function: #Function<9.80215867/0 in Mimic.Server.handle_call/3>
Args: []
11:25:03.769 [error] Task #PID<0.1667.0> started from #PID<0.94.0> terminating
** (stop) exited in: GenServer.call(Mimic.Server, {:reset, App1}, 60000)
** (EXIT) an exception was raised:
** (MatchError) no match of right hand side value: {:error, {:cant_open_file, '/apps/app_1/Elixir.App1-566835.coverdata', :enoent}}
(mimic 1.7.1) lib/mimic/cover.ex:32: Mimic.Cover.replace_coverdata!/3
(elixir 1.13.3) lib/task/supervised.ex:89: Task.Supervised.invoke_mfa/2
(elixir 1.13.3) lib/task/supervised.ex:34: Task.Supervised.reply/4
(stdlib 3.17.1) proc_lib.erl:226: :proc_lib.init_p_do_apply/3
(elixir 1.13.3) lib/gen_server.ex:1030: GenServer.call/3
(elixir 1.13.3) lib/enum.ex:937: Enum."-each/2-lists^foreach/1-0-"/2
(ex_unit 1.13.3) lib/ex_unit/runner.ex:64: ExUnit.Runner.run_with_trap/2
(ex_unit 1.13.3) lib/ex_unit/runner.ex:31: ExUnit.Runner.run/2
(elixir 1.13.3) lib/task/supervised.ex:89: Task.Supervised.invoke_mfa/2
(elixir 1.13.3) lib/task/supervised.ex:34: Task.Supervised.reply/4
(stdlib 3.17.1) proc_lib.erl:226: :proc_lib.init_p_do_apply/3
Function: #Function<0.129552615/0 in ExUnit.async_run/0>
Args: []
** (EXIT from #PID<0.94.0>) exited in: GenServer.call(Mimic.Server, {:reset, App1}, 60000)
** (EXIT) an exception was raised:
** (MatchError) no match of right hand side value: {:error, {:cant_open_file, '/apps/app_1/Elixir.App1-566835.coverdata', :enoent}}
(mimic 1.7.1) lib/mimic/cover.ex:32: Mimic.Cover.replace_coverdata!/3
(elixir 1.13.3) lib/task/supervised.ex:89: Task.Supervised.invoke_mfa/2
(elixir 1.13.3) lib/task/supervised.ex:34: Task.Supervised.reply/4
(stdlib 3.17.1) proc_lib.erl:226: :proc_lib.init_p_do_apply/3
I went and added some IO.puts
into the mimic lib to see if I can hunt it down a bit.
COPIED:
text to ensure_module_copied
where it gets the coverdata_path from Module.replace!
Replacing cover data for
in replace_coverdata!
and am printing out the original_coverdata_path
and path
Deleting
in replace_coverdata!
and am printing out both paths right before it delets.Here's the results (trimmed up a bit wit some renaming)
==> app_1
Cover compiling modules ...
COPIED: /apps/app_1/Elixir.App1-566835.coverdata
COPIED: /apps/app_1/Elixir.App1.Thing-566835.coverdata
...mix test output...
Randomized with seed 421312
Replacing cover data for original: /apps/app_1/Elixir.App1.Thing-566835.coverdata
Replacing cover data for original: /apps/app_1/Elixir.App1-566835.coverdata
Replacing cover data for path: /apps/app_1/Elixir.App1.Thing.Mimic.Original.Module-566835.coverdata
Replacing cover data for path: /apps/app_1/Elixir.App1.Mimic.Original.Module-566835.coverdata
Deleting /apps/app_1/Elixir.App1.Thing.Mimic.Original.Module-566835.coverdata
Deleting /apps/app_1/Elixir.App1.Thing-566835.coverdata
Deleting /apps/app_1/Elixir.App1.Mimic.Original.Module-566835.coverdata
Deleting /apps/app_1/Elixir.App1-566835.coverdata
Generating cover results ...
...coverage results output...
Analysis includes data from imported files
["/apps/app_1/Elixir.App1.Thing-566835.coverdata",
"/apps/app_1/Elixir.App1.Thing.Mimic.Original.Module-566835.coverdata"]
Analysis includes data from imported files
["/apps/app_1/Elixir.App1-566835.coverdata",
"/apps/app_1/Elixir.App1.Mimic.Original.Module-566835.coverdata"]
Generated HTML coverage results in "cover" directory
==> app_2
Cover compiling modules ...
...mix test output...
Randomized with seed 421312
Replacing cover data for original: /apps/app_1/Elixir.App1-566835.coverdata
Replacing cover data for path: /apps/app_2/Elixir.App1.Mimic.Original.Module-566835.coverdata
11:25:03.762 [error] Task #PID<0.1852.0> started from Mimic.Server terminating
...rest of the same error...
The problem seems to exist in the second app. It appears to be using the wrong path for the original coverdata path. The file is actually located at /apps/app_2/Elixir.App1-566835.coverdata
. It stills has the old path from when app_1
test had ran and did not properly clear out between apps test runs. It also doesn't seem to copy the module (COPIED
) and so it's path stored in the state is still the same from the original copy from it running in the first app.
Hi, when i was using Mimic (version 1.2.0) as mock library, i was stumped by this error
** (UndefinedFunctionError) function :cover.compile_beams/1 is undefined or private. Did you mean one of:
* compile/1
* compile/2
* compile_beam/1
* compile_beam_directory/0
* compile_beam_directory/1
:cover.compile_beams([{CoronaNews.Gateway.Mimic.Original.Module, <<70, 79, 82, 49, 0, 0, 16, 208, 66, 69, 65, 77, 65, 116, 85, 56, 0, 0, 2, 31, 0, 0, 0, 43, 47, 69, 108, 105, 120, 105, 114, 46, 67, 111, 114, 111, 110, 97, 78, 101, 119, 115, 46, 71, 97, 116, 101, ...>>}])
lib/mimic/module.ex:45: Mimic.Module.rename_module/2
lib/mimic/module.ex:27: Mimic.Module.replace!/1
lib/mimic.ex:338: Mimic.copy/1
test/test_helper.exs:1: (file)
only when i revert mimic to version 1.0.0 that this error fixed
Here is code on test_helper.exs
# at test_helper.ex
Mimic.copy(CoronaNews.Gateway)
Application.ensure_started(:mimic)
ExUnit.start()
here is my iex -v
Erlang/OTP 22 [erts-10.6.1] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [hipe]
IEx 1.9.4 (compiled with Erlang/OTP 21)
Hello,
So recently i realize if you call a function that have a stub with a function in the same module that does not have stub.
The second function is actually calling the original function of the stubbed function.
Is there a way to overcome this limitation and make the second function to call the stub instead of the original function.
Thank you.
PS: If it's not possible it's alright, I'll create a separate module that will be the one that i make as a module for stubbed function.
this isn't a terribly big deal but at my company we've got a really slow start up time for tests. Currently it takes 13 seconds just to start up the test (not even run the test, not even compile either).
The biggest culprit is Prometheus, which is taking up 8-9 seconds of application start up time. Removing that library and stubbing out all it's modules, mimic comes in 2nd place at 481ms.
Wow 481ms? That's not a lot! :D but when it comes to having a fast TDD cycle, it's annoying to have to wait 4 seconds (even 13!) for unit test to start running. (Mind you, I'm also trying to figure out why the other libraries are also taking their time)
A way to show mimic takes half a second is by running
> time MIX_ENV=prod mix run
warning: use Mix.Config is deprecated. Use the Config module instead
config/config.exs:1
real 0m0.937s
user 0m0.744s
sys 0m0.314s
Dylan@DylansWorkMBPM1:(main)~/Development/solve/mimic
> time MIX_ENV=prod mix run --no-start
warning: use Mix.Config is deprecated. Use the Config module instead
config/config.exs:1
real 0m0.526s
user 0m0.330s
sys 0m0.319s
Both commands have compilation/IO overheads, the latter doesn't start up any applications. (prod env to avoid compiling dialyzer and such). The difference is about 400ms.
I'm curious really, why does it take almost half a second to start up Mimic? I understand that they're likely won't be any changes, but I'm curious than anything right now.
Is the Mimic expected behavior to fail an expectation if the original implementation gets called with different arguments than the one defined in the expect
function?
defmodule Test do
def call(arg), do: true
end
Test
|> expect(:call, 1, fn 2 -> true end)
Test.call(3)
Is the above supposed to fail verification?
Trying to stub the Integer.to_string/2
method does not work.
# test_helper.exs
Mimic.copy(Integer)
ExUnit.start()
# test/sometest.exs
defmodule SomeTest do
use ExUnit.Case
use Mimic
test "greets the world" do
stub(Integer, :to_string, fn _ -> "STUB" end)
stub(Integer, :to_string, fn _, _ -> "STUB" end)
random = Integer.to_string(5)
assert random == "STUB"
end
end
It seems the above test will fail, but if it's for some other method, like Integer.digits/1
it passes.
Not really sure what could be the issue without further investigation. ๐ค
EDIT: I'll be more than happy to open an example repo reproducing the issue ๐
Hi @edgurgel ,
Is it good to make Mimic.copy optional/faster so that starting mix test
would be faster?
recently i was practicing TDD at a project at work which use Mimic a lot, during that time, i realize that Mimic.copy
is taking a long time, making the starting of test (mix app.start test/some_test.exs
) become really slow. that project was having Mimic.copy
~100 module. and the reason Mimic.copy
is slow is because one of the operation, rename_module
is slow, it was decompiling & recompiling module to rename it. if the module size is big, then rename_module
would take long time to finish.
currently i was hacking it to make sure when i was in TDD_MODE, test_helper.exs would disable most of Mimic.copy
, with this i reduce test startup time from ~45 second to ~5 second.
I was considering on how to solve this problem in general, some ideas:
Mimic.copy
, the idea is at test file, there's a function which would run Mimic.copy
if a particular module isn't copied before (with unique single worker to make sure async test doesn't have problem), it looks somewhat like this#test_helper.exs
if not tdd_mode? do
Mimic.copy(MockedModule)
...
end
#test/some_test.exs
defmodule SomeTest do
setup do
Mimic.ensure_copied!(MockedModule)
end
test "some test" do
Mimic.stub(MockedModule ....)
...
end
end
Elixir version: 1.10.3, OTP 22, Mimic version 1.5.0
Lets say, we've following module & test:
defmodule Calculator do
def calculate(:div, num1, num2) do
divide(num1, num2)
end
def calculate(_, num1, num2) do
// do other things
end
def divide(num1, 0), do: :error
def divide(num1, num2), do: num1 / num2
end
reject(&Calculator.divide/2)
Calculator.calculate(:add, 3, 4)
expect(Calculator, :divide, fn _, _ -> 42 end)
Calculator.calculate(:div, 100, 5)
Right now, it gives Mimic.UnexpectedCallError
which makes sense. I wanted to assert no call was made on the first round but on second round, it does make call and the expect
should work but reject
needs to be invalidated at this point via some construct.
I tried doing:
reject(&Calculator.divide/2)
Calculator.calculate(:add, 3, 4)
verify!()
expect(Calculator, :divide, fn _, _ -> 42 end)
Calculator.calculate(:div, 100, 5)
But it does not seem to work. Can we have a simple API to achieve this? Of course, in most cases, we can probably split the test into two cases but this is just a contrived example and sometimes for real world stuff, need that within a single test case.
There are many cases where I want to call the original function some number of times before then wanting to do something different, or perhaps wanting to call the original function conditionally dependent on the arguments.
I'm not aware of a current way of grabbing the original function. When I attempt this:
original = &MyModule.function/3
even if done before calling expect
, I get the mocked function.
Hey!
I have a project where we use Mimic to copy a few modules, worked perfectly until we tried to copy a module that was basically a NIF module:
# nif module
defmodule Core.Crypto.Ethereum do
use Rustler, otp_app: :core, crate: :core_crypto_ethereum
def ens_lookup_address(_), do: :erlang.nif_error(:nif_not_loaded)
end
# test_helpers.exs
# ...
# a bunch of Mimic.copy/1 calls here
Mimic.copy(Core.Crypto.Ethereum)
ExUnit.start()
# test:
defmodule MyTest do
use Core.DataCase, async: true
import Mimic
describe "some function" do
test "example" do
expect(Core.Crypto.Ethereum, :ens_lookup_address, fn _ -> {:ok, "example.eth"} end)
assert true
end
end
end
Output:
** (ArgumentError) Module Core.Crypto.Ethereum has not been copied. See docs for Mimic.copy/1
code: expect(Ethereum, :ens_lookup_address, fn _addr -> {:ok, "example.eth"} end)
stacktrace:
(mimic 1.7.4) lib/mimic.ex:498: Mimic.validate_server_response/2
test/core/services/my_test.exs:49: (test)
# ...
18:43:45.063 [error] GenServer Mimic.Server terminating
** (stop) {:error_loading_module, Core.Crypto.Ethereum.Mimic.Original.Module, :on_load_failure}
(mimic 1.7.4) lib/mimic/module.ex:87: Mimic.Module.load_binary/3
(mimic 1.7.4) lib/mimic/module.ex:57: Mimic.Module.rename_module/2
(mimic 1.7.4) lib/mimic/module.ex:34: Mimic.Module.replace!/1
(mimic 1.7.4) lib/mimic/server.ex:504: Mimic.Server.ensure_module_copied/2
(mimic 1.7.4) lib/mimic/server.ex:360: Mimic.Server.handle_call/3
(stdlib 4.0.1) gen_server.erl:1146::gen_server.try_handle_call/4
(stdlib 4.0.1) gen_server.erl:1175::gen_server.handle_msg/6
(stdlib 4.0.1) proc_lib.erl:240: :proc_lib.init_p_do_apply/3
Last message (from #PID<0.2767.0>): {:expect, {Core.Crypto.Ethereum, :ens_lookup_address, #Function<4.71929683/1 in Core.MyTest."test example"/1>, 1}, 1, #PID<0.2767.0>}
This was a super-bizarro one that I just came across! I've tried to minimize the example as much as I can.
Given a module that defines a struct, eg.
defmodule Log do
defstruct [:name]
def hello, do: nil
end
I can use that struct quite happily in tests -
# in test
dbg(%Log{})
# prints out
%Log{} #=> %Log{name: nil}
but if I want to stub out a function on that module, it throws up a really confusing error
# in test
stub(Log, :hello, fn -> "hello" end)
dbg(%Log{})
# prints out
%Log{} #=> #Inspect.Error<
got Protocol.UndefinedError with message:
"""
protocol Enumerable not implemented for nil of type Atom. This protocol is implemented for
the following type(s): DBConnection.PrepareStream, DBConnection.Stream, Date.Range,
Ecto.Adapters.SQL.Stream, File.Stream, Floki.HTMLTree, Function, GenEvent.Stream, HashDict,
HashSet, IO.Stream, IP.Prefix, Jason.OrderedObject, List, Map, MapSet, MerkleMap,
Phoenix.LiveView.LiveStream, Postgrex.Stream, Range, Stream, StreamData
"""
while inspecting:
%{__struct__: Log, name: nil}
Stacktrace:
(elixir 1.14.3) lib/enum.ex:1: Enumerable.impl_for!/1
(elixir 1.14.3) lib/enum.ex:166: Enumerable.reduce/3
(elixir 1.14.3) lib/enum.ex:4307: Enum.reduce/3
(elixir 1.14.3) lib/inspect.ex:595: Inspect.Any.inspect/2
(elixir 1.14.3) lib/inspect/algebra.ex:341: Inspect.Algebra.to_doc/2
(elixir 1.14.3) lib/kernel.ex:2254: Kernel.inspect/2
(elixir 1.14.3) lib/macro.ex:2576: Macro.dbg_format_ast_to_debug/2
(elixir 1.14.3) lib/macro.ex:2546: Macro.__dbg__/3
test/my_app/my_test.exs:44: MyApp.MyTest."test stuff"/1
(ex_unit 1.14.3) lib/ex_unit/runner.ex:512: ExUnit.Runner.exec_test/1
(stdlib 4.3.1) timer.erl:235: :timer.tc/1
(ex_unit 1.14.3) lib/ex_unit/runner.ex:463: anonymous fn/4 in ExUnit.Runner.spawn_test_monitor/4
>
I can't work out if this is an error in displaying the struct, or actually using the struct for things. As I want to use the struct in assertions for tests, trying to print out test failures is itself raising protocol errors like this, and it's rather confusing!
I mimicked Code
module so I could test with and without optional dependencies
Code
|> expect(:ensure_loaded?, fn Mojito -> true end)
|> expect(:ensure_loaded?, fn Jason -> false end)
Everything looked like it was working well, and tests passing, but then I get this ** (EXIT from #PID<0.93.0>) killed
error right after the test run and gives me an exit code of 1
, which will mess up CI. :(
Finished in 0.07 seconds (0.07s async, 0.00s sync)
6 tests, 0 failures
Randomized with seed 27160
** (EXIT from #PID<0.93.0>) killed
If I comment out the tests that use Code
mocks, I still get the error until I comment out Mimic.copy(Code)
from test helpers.
Is there any hope of this working, or anything I can do?
I'm writing some generic code for my tests that calls Mimic's allow/3
on Task.async
when in the test environment, so that I can write async code without worrying whether it's going to be testable or not.
The problem is if no stubs or expectations were created for the Mock, the allow/3
call raises since there's no case for an empty list. I'm working around this in my own code by calling :ets
directly as if I were Mimic, but would prefer a less hacky solution.
I could do a PR for this, but there are multiple possible solutions, wondering what you think would be preferrable:
allow
.Mimic
module for inspecting the existing stubs/expectations on a Mock.Thanks!
Edit: it'd also be useful to access the currently active mode, since we can't allow
when :global
. I'm using :sys.get_state(Mimic.Server)
atm as a workaround.
Hey Folks. I noticed Mimic is not able to see a function when this function is called without its module name.
For example:
defmodule Transactions do
def delete(guids) do
delete_something(guids)
end
def delete_something(guids) do
{:ok, guids}
end
end
Mimic.copy(Transactions)
Transactions
|> expect(:delete_something, fn transaction_guids ->
IO.inspect("Hey")
{:ok, transaction_guids}
end)
Transactions.delete([])
** (Mimic.VerificationError) error while verifying mocks for #PID<0.2950.0>:
* expected Transactions.delete_something/1 to be invoked 1 time(s) but it has been called 0 time(s)
To fix this we need to call this way:
__MODULE__.delete_something(guids)
Can I open a PR to fix this? What do you folks think?
When mocking external service calling modules, such as HTTP and gRPC, we might not want to these to be called without being mocked.
It would be nice to have a way to configure Mimic to raise an error when calling a copied function, such as WebMock (https://github.com/bblimke/webmock) does on Ruby with WebMock.disable_net_connect!
, to block real web requests.
Hi @edgurgel , would adding support for stubs_with
functionality, a function to completely mock a module with another module, is something that align with Mimic
?
stubs_with
would have similar behaviour to Mox, which is:
short example that i can think of is like
defmodule RedisCache do
def fetch_cache(key), do: ...
def put_cache(key, value), do: ...
end
....
defmodule TestRedisCache do
# SImple cache by process dictionary
def get_cache(key), do: Process.get(key, :none_value)
end
def put_cache(key, value), do: Process.put(key, value)
end
....
#test_helper.ex
Mimic.stubs_with(RedisCache, TestRedisCache)
when trying to copy erlang modules there is an error printed out and copying doesn't succeed, is this intended? how can i copy/mock these kind of modules? thanks
15:32:21.833 [error] Can't load module ':rpc' that resides in sticky dir
1) test success registering with manager (Worker.RegisterTest)
apps/worker/test/regiser_test.exs:7
** (ArgumentError) Module :rpc has not been copied. See docs for Mimic.copy/1
code: expect(:rpc, :call, fn args ->
stacktrace:
(mimic) lib/mimic.ex:423: Mimic.raise_if_not_copied!/1
(mimic) lib/mimic.ex:200: Mimic.expect/4
test/regiser_test.exs:9: (test)
Version 1.7.4
Hi, I've noticed that if the number of calls exceeds the expected count (default 1) on a mocked function, it reverts to calling the original function. I would have expected it to raise an error.
Is the behavior deliberate? I wanted to check before raising a documentation PR.
(I've a workaround involving initially stubbing with a stub-which-flunks (tm)).
warning: this clause for __mimic_info__/0 cannot match because a previous clause at line 94 always matches
.../_deps/mimic/lib/mimic/module.ex:94
This seems to be caused by Mimic.copy(MyModule)
in test/support/bla.ex
. bla.ex
's function gets called in the setup
block of the test
We are depending on :cover
right now. We should use :cover
just if available.
currently, the expect/3
api only performs call assertion at the end of the test case. However, there are situations where it is ideal to make call assertions throughout the test case (e.g. that api calls are made correctly, args are correct, etc), much like how :meck
exposes a few functions to make call assertions easier.
Are there plans for such an API? I can dig into this and raise a PR if so.
Currently, expect/4 takes in an optional parameter for the amount of calls expected for the function.
If this value is not provided, it seems to default to 1
.
We have a test scenario that a function might be called once or twice, and either case we just want the function to return the same mock we are setting up. (ie expect(Module, :method_name, fn _ -> :ok end)
)
Is there a way to accomplish this with mimic? If not, would it be possible to add this as a functionality? Thank you!
When I update mimic to the latest version in a project I work on it breaks test coverage.
12:43:43.169 [error] Task #PID<0.13868.0> started from Mimic.Server terminating
** (MatchError) no match of right hand side value: {:error, {:not_cover_compiled, Synapse.AppRequest.Application.Mimic.Original.Module}}
(mimic 1.7.4) lib/mimic/cover.ex:52: Mimic.Cover.export_coverdata!/1
(mimic 1.7.4) lib/mimic/cover.ex:32: Mimic.Cover.clear_module_and_import_coverdata!/3
(elixir 1.14.2) lib/task/supervised.ex:89: Task.Supervised.invoke_mfa/2
(elixir 1.14.2) lib/task/supervised.ex:34: Task.Supervised.reply/4
(stdlib 4.2) proc_lib.erl:240: :proc_lib.init_p_do_apply/3
Function: #Function<9.132716098/0 in Mimic.Server.handle_call/3>
When running mix test--stale
from the top level of an umbrella app, and you have Mimic.copy(M)
in two different app test_helper files, you'll get this error upon rerunning the tests with --stale
(dunno why it doesnt happen without stale).
** (ArgumentError) Module M has already been copied. See docs for Mimic.copy/1
(mimic 1.7.2) lib/mimic.ex:506: Mimic.validate_server_response/2
test/test_helper.exs:1: (file)
(elixir 1.13.1) lib/code.ex:1183: Code.require_file/2
Unsure what the underlying issue is, but if Mimic ignored double copy
s then we'd maybe be ok.
Hey Jerk.
I tried to add Mimic to a project which hasn't been reupped to the latest and greatest and got the following error at compile time:
** (UndefinedFunctionError) function :cover.compile_beams/1 is undefined or private. Did you mean one of:
* compile/1
* compile/2
* compile_beam/1
* compile_beam_directory/0
* compile_beam_directory/1
:cover.compile_beams([{Backbone.Charge.HookHandler.Mimic.Original.Module, <<70, 79, 82, 49, 0, 0, 36, 32, 66, 69, 65, 77, 65, 116, 85, 56, 0, 0, 4, 48, 0, 0, 0, 65, 56, 69, 108, 105, 120, 105, 114, 46, 66, 97, 99, 107, 98, 111, 110, 101, 46, 67, 104, 97, 114, 103, 101, ...>>}])
lib/mimic/module.ex:45: Mimic.Module.rename_module/2
lib/mimic/module.ex:27: Mimic.Module.replace!/1
lib/mimic.ex:343: Mimic.copy/1
test/test_helper.exs:3: (file)
The output of elixir --version
:
Erlang/OTP 22 [erts-10.6.4] [source] [64-bit] [smp:12:12] [ds:12:12:10] [async-threads:1] [hipe]
Elixir 1.9.4 (compiled with Erlang/OTP 22)
I had to go all the way back to Mimic 1.0.0 to get it to work.
Thanks!
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.