View Source Isolation modes

Repatch has 3 different isolation modes for patch isolation when testing with async: true, and it is important to know when and how to use each one of them.

Local mode

This mode is always enabled and isolates applied patches only to the current process. Any other process will be unable to execute the patch that this process set. However, local patches do not affect other processes and it is completely safe to use this mode with async: true testing option. This mode is also the fastest one in terms of runtime overhead.

Shared mode

This mode is enabled by default but it can be disabled with enable_shared: false option in the Patch.setup/1 call. It isolates the patch for the current process, Task processes it creates and any allowed process. This mechanic is similar to testing with allowances in Ecto and Mox, though it is slightly different. Use Repatch.allow/2 to share the patch with other processes.

Consider this example

pid = Server.start()

# Everything works as expected without patch
assert %MapSet{} = Server.call(pid, MapSet, :new, [])
assert %MapSet{} = MapSet.new()

# Now we apply patch and prove that only current process sees it
Repatch.patch(MapSet, :new, [mode: :shared], fn -> :hello end)
assert %MapSet{} = Server.call(pid, MapSet, :new, [])
assert :hello = MapSet.new()

# And now we allow the server to have access to this patch and we see
# that it resolves to the same patch as the current process
Repatch.allow(self(), pid)
assert :hello = Server.call(pid, MapSet, :new, [])
assert :hello = MapSet.new()

Due to it's nature, it is also safe to use this mode with async: true testing option. However, if two tests running at the same time, will try to allow the same third process to call shared patches, one of the allow calls will fail, so it's up to developer to make sure that processes are not shared between tests.

It also has integration with Task module similar to Mox's one, and it allows spawned tasks to call the patches of their original caller automatically (without explicit Repatch.allow/3 call).

Global mode

This mode is disabled by default and must be enabled with enable_global: true option in Patch.setup call. It doesn't isolate the patch in any way, what means that the patch will be accessible by the current process and any other process. This mechanic is similar to testing with Patch library or global mode in Mox.