{"id":13564484,"url":"https://github.com/ihumanable/patch","last_synced_at":"2026-02-21T18:02:15.561Z","repository":{"id":41138933,"uuid":"257743317","full_name":"ihumanable/patch","owner":"ihumanable","description":"Ergonomic Mocking for Elixir","archived":false,"fork":false,"pushed_at":"2025-06-03T21:22:01.000Z","size":312,"stargazers_count":214,"open_issues_count":11,"forks_count":13,"subscribers_count":1,"default_branch":"master","last_synced_at":"2026-02-18T05:10:35.207Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Elixir","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ihumanable.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2020-04-21T23:52:35.000Z","updated_at":"2026-01-16T02:01:27.000Z","dependencies_parsed_at":"2023-02-01T01:15:37.350Z","dependency_job_id":"35b00363-8f8e-4ec5-8e12-d02ae1f2d88f","html_url":"https://github.com/ihumanable/patch","commit_stats":{"total_commits":95,"total_committers":5,"mean_commits":19.0,"dds":0.3894736842105263,"last_synced_commit":"c4e3dfd791f4cb218af0586bd7f9b7a94d62f83f"},"previous_names":[],"tags_count":20,"template":false,"template_full_name":null,"purl":"pkg:github/ihumanable/patch","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ihumanable%2Fpatch","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ihumanable%2Fpatch/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ihumanable%2Fpatch/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ihumanable%2Fpatch/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ihumanable","download_url":"https://codeload.github.com/ihumanable/patch/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ihumanable%2Fpatch/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29689644,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-21T15:51:39.154Z","status":"ssl_error","status_checked_at":"2026-02-21T15:49:03.425Z","response_time":107,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-01T13:01:32.050Z","updated_at":"2026-02-21T18:02:15.525Z","avatar_url":"https://github.com/ihumanable.png","language":"Elixir","funding_links":[],"categories":["Testing"],"sub_categories":[],"readme":"# Patch\n\n[![CI](https://github.com/ihumanable/patch/workflows/CI/badge.svg)](https://github.com/ihumanable/patch/actions)\n[![Hex.pm Version](http://img.shields.io/hexpm/v/patch.svg?style=flat)](https://hex.pm/packages/patch)\n[![Hex.pm License](http://img.shields.io/hexpm/l/patch.svg?style=flat)](https://hex.pm/packages/patch)\n[![HexDocs](https://img.shields.io/badge/HexDocs-Yes-blue)](https://hexdocs.pm/patch)\n\nPatch - Ergonomic Mocking for Elixir\n\nPatch makes it easy to replace functionality in tests with test specific functionality.  Patch augments ExUnit with several utilities that make writing tests in Elixir fast and easy.  Patch includes unique functionality that no other mocking library for Elixir provides, Patch's [Super Powers](https://hexdocs.pm/patch/super-powers.html).\n\n## Features\n\nWhy use Patch instead of meck, Mock, Mockery, Mox, etc?  \n\nPatch starts with a very simple idea for how a patched function should work.\n\n\u003e Patched functions should **always** return the mock value they are given.\n\nHere are the key features of Patch.\n\n1. Easy-to-use and composable interface with sensible defaults.\n2. First class support for working with Processes.\n3. No testing code in non-test code.\n\nIn addition to these features which many libraries aspire to, Patch has 3 additional features that no other mocking library for Elixir / Erlang seem to have.  These [Super Powers](https://hexdocs.pm/patch/super-powers.html) are \n\n1. Patch mocks are effective for both local and remote calls.  This means a patched function **always** resolves to the patch.\n2. Patch can patch private functions without changing their visibility.\n3. Patch makes it possible to test your private functions without changing their visibility via the `expose/2` functionality.  \n\nSee the [Mockompare](https://github.com/ihumanable/mockompare) companion project for a comparison of Elixir / Erlang mocking libraries.  If there is a way to accomplish the following with another library, please open an issue so this section and the comparisons can be updated.\n\nFor more information about Patch's Super Powers see the [Super Powers Documentation](https://hexdocs.pm/patch/super-powers.html)\n\n## Table of Contents\n\n- [Installation](#installation)\n- [Quickstart](#quickstart)\n  - [Core Functions](#core-functions)\n  - [Assertions](#assertions)\n  - [Value Builders](#value-builders)\n  - [Customizing Imports](#customizing-imports)\n- [Guide Book](#guide-book)\n- [Support Matrix](#support-matrix)\n- [Limitations](#limitations)\n- [Prior Art](#prior-art)\n- [Changelog](#changelog)\n\n## Installation\n\nAdd patch to your mix.exs\n\n```elixir\ndef deps do\n  [\n    {:patch, \"~\u003e 0.16.0\", only: [:dev, :test]}\n  ]\nend\n```\n\nPatch also provides formatter rules for `mix format` if you would like to use these rules add\n\n```elixir\nimport_deps: [:patch]\n```\n\nto your `.formatter.exs` file.\n\n## Quickstart\n\nAfter adding the dependency just add the following line to any test module after using your test case\n\n```elixir\nuse Patch\n```\n\nThis library comes with a comprehensive suite of unit tests.  These tests not only verify that the library is working correctly but are designed so that for every bit of functionality there is an easy to understand example for how to use that feature.  Check out the [User Tests](https://github.com/ihumanable/patch/tree/master/test/user) for examples of how to use each feature.\n\nUsing Patch adds 11 core functions, 10 assertions, 7 mock value builders, and 1 utility function to the test.  These imports can be controlled, see the [Customizing Imports](#customizing-imports) for details.\n\nSee the [Cheatsheet](https://hexdocs.pm/patch/cheatsheet.html) for an overview of how the library can be used and as a handy reference.  Continue below for links to more in-depth documentation including the [Guidebook](https://hexdocs.pm/patch/01-introduction.html).\n\n### Core Functions\n\nCore functions let us apply patches, patch processes, intercept messages, and query our patched modules.\n\n| Core Function                                                | Description                                                                          |\n|--------------------------------------------------------------|--------------------------------------------------------------------------------------|\n| [expose/2](https://hexdocs.pm/patch/Patch.html#expose/2)     | Expose private functions as public for the purposes of testing                       |\n| [fake/2](https://hexdocs.pm/patch/Patch.html#fake/2)         | Replaces a module with a fake module                                                 |\n| [history/1,2](https://hexdocs.pm/patch/Patch.html#history/2) | Returns the call history for a mock                                                  |\n| [inject/3,4](https://hexdocs.pm/patch/Patch.html#inject/4)   | Injects a listener into a GenServer                                                  |\n| [listen/3](https://hexdocs.pm/patch/Patch.html#listen/3)     | Intercepts messages to a process and forwards them to the test process               |\n| [patch/3](https://hexdocs.pm/patch/Patch.html#patch/3)       | Patches a function so that it returns a mock value                                   |\n| [private/1](https://hexdocs.pm/patch/Patch.html#private/1)   | Macro to call exposed private functions without raising a compiler warning           |\n| [real/1](https://hexdocs.pm/patch/Patch.html#real/1)         | Resolves the real module for a patched module                                        |\n| [replace/3](https://hexdocs.pm/patch/Patch.html#replace/3)   | Replaces part of the state of a GenServer                                            |\n| [restore/1,2](https://hexdocs.pm/patch/Patch.html#restore/1) | Restores an entire module or just a function within a module to its pre-patched form |\n| [spy/1](https://hexdocs.pm/patch/Patch.html#spy/1)           | Patches a module so calls can be asserted without changing behavior                  |\n\n### Assertions\n\nAssertions make it easy to assert that a patched module has or has not observed a call.\n\n| Assertion                                                                        | Description                                                                                                   |\n|----------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------|\n| [assert_any_call/1](https://hexdocs.pm/patch/Patch.html#assert_any_call/1)       | Asserts that any call of any arity has occurred on the mocked module for a function name (preferred macro)    |\n| [assert_any_call/2](https://hexdocs.pm/patch/Patch.html#assert_any_call/2)       | Asserts that any call of any arity has occurred on the mocked module for a function name (advanced use cases) |\n| [assert_called/1](https://hexdocs.pm/patch/Patch.html#assert_called/1)           | Asserts that a particular call has occurred on a mocked module                                                |\n| [assert_called/2](https://hexdocs.pm/patch/Patch.html#assert_called/2)           | Asserts that a particular call has occurred a given number of times on a mocked module                        |\n| [assert_called_once/1](https://hexdocs.pm/patch/Patch.html#assert_called_once/2) | Asserts that a particular call has occurred exactly once on a mocked module                                   |\n| [refute_any_call/1](https://hexdocs.pm/patch/Patch.html#refute_any_call/1)       | Refutes that any call of any arity has occurred on the mocked module for a function name (preferred macro)    |\n| [refute_any_call/2](https://hexdocs.pm/patch/Patch.html#refute_any_call/2)       | Refutes that any call of any arity has occurred on the mocked module for a function name (advanced use cases) |\n| [refute_called/1](https://hexdocs.pm/patch/Patch.html#refute_called/1)           | Refutes that a particular call has occurred on a mocked module                                                |\n| [refute_called/2](https://hexdocs.pm/patch/Patch.html#refute_called/2)           | Refutes that a particular call has occurred a given number of time on a mocked module                         |\n| [refute_called_once/1](https://hexdocs.pm/patch/Patch.html#refute_called_once/1) | Refutes that a particular call has occurred exactly once on a mocked module                                   |\n\n### Value Builders\n\nPatched functions aren't limited to only returning simple scalar values, a host of Value Builders are provided for all kinds of testing scenarios.  See the [patch](https://hexdocs.pm/patch/Patch.html#patch/3) documentation for details.\n\n| Value Builder                                                             | Description                                                                                              |\n|---------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------|\n| [callable/1,2](https://hexdocs.pm/patch/Patch.Mock.Value.html#callable/2) | Callable that will be invoked on every patch invocation, dispatch and evaluation modes can be customized |\n| [cycle/1](https://hexdocs.pm/patch/Patch.Mock.Value.html#cycle/1)         | Cycles through the values provided on every invocation                                                   |\n| [raises/1](https://hexdocs.pm/patch/Patch.Mock.Value.html#raises/1)       | Raises a RuntimeException with the given message upon invocation                                         |\n| [raises/2](https://hexdocs.pm/patch/Patch.Mock.Value.html#raises/2)       | Raises the specified Exception with the given attribtues upon invocation                                 |\n| [scalar/1](https://hexdocs.pm/patch/Patch.Mock.Value.html#scalar/1)       | Returns the argument as a literal, useful for returning functions                                        |\n| [sequence/1](https://hexdocs.pm/patch/Patch.Mock.Value.html#sequence/2)   | Returns the values in order, repeating the last value indefinitely                                       |\n| [throws/1](https://hexdocs.pm/patch/Patch.Mock.Value.html#throws/1)       | Throws the given value upon invocation                                                                   |\n\n### Utility Functions\n\nPatch comes with some utilities that can assist when tests aren't behaving as expected.\n\n| Utility Function                                         | Description                                   |\n|----------------------------------------------------------|-----------------------------------------------|\n| [debug/0,1](https://hexdocs.pm/patch/Patch.html#debug/1) | Enable or Disable debug mode for a given test |\n\n### Customizing Imports\n\nBy default, Patch will import the functions listed in the previous sections.  Imports can be customized through the `:only`, `:except` and `:alias` options.\n\n`:only` and `:except` work similiarly to how they work for the `import` except the values are either a list of symbol atoms or the special atom `:all`.\n\nHere's how only the `expose`, `patch`, and `private` symbols can be imported.\n\n```elixir\nuse Patch, only: [:expose, :patch, :private]\n```\n\nHere's how every symbol except `throws` can be imported\n\n```elixir\nuse Patch, except: [:throws]\n```\n\nPatch also allows you to alias imported symbols, to import `patch` as `mock` the following would be used.\n\n```elixir\nuse Patch, alias: [patch: :mock]\n```\n\n## Guide Book\n\nPatch comes with [plenty of documentation](https://hexdocs.pm/patch) and a [Suite of User Tests](https://github.com/ihumanable/patch/tree/master/test/user) that show how to use the library.  \n\nFor a guided tour and deep dive of Patch, see the [Guide Book](https://hexdocs.pm/patch/01-introduction.html)\n\n## Support Matrix\n\nTests automatically run against a matrix of OTP and Elixir Versions, see the [ci.yml](https://github.com/ihumanable/patch/tree/master/.github/workflows/ci.yml) for details.\n\n| OTP \\ Elixir | 1.11 | 1.12 | 1.13 | 1.14 | 1.15 | 1.16 | 1.17 | 1.18 |\n|:------------:|:----:|:----:|:----:|:----:|:----:|:----:|:----:|:----:|\n| 24           | ✅   | ✅   | ✅   | ✅   | ✅   | N/A  | N/A  | N/A  |\n| 25           | N/A   | N/A   | ✅   | ✅   | ✅   | ✅   | ✅   | N/A    |\n| 26           | N/A   | N/A   | N/A   | ✅   | ✅   | ✅   | ✅   | ✅   |\n| 27           | N/A   | N/A   | N/A   | N/A   | N/A   | N/A   | ✅   | ✅   |\n\n## Limitations\n\nPatch works by recompiling modules, this alters the global execution environment. \n\nSince the global execution environment is altered by Patch, **Patch is not compatible with async: true**.\n\n## Prior Art\n\nUp to version 0.5.0 Patch was based off the excellent [meck](https://hex.pm/packages/meck) library.  Patch [Super Powers](https://hexdocs.pm/patch/super-powers.html) required a custom replacement for meck, `Patch.Mock`.  \n\nPatch also takes inspiration from python's [unittest.mock.patch](https://docs.python.org/3/library/unittest.mock.html#patch) for API design.\n\n## Contributors\n\nPatch is made better everyday by developers requesting new features.  \n\n- [daisyzhou](https://github.com/daisyzhou)\n  - Suggested the new function pass through behavior introduced in v0.9.0\n- [likeanocean](https://github.com/likeanocean)\n  - Suggested `assert_called/2`, `assert_called_once/1`, `refute_called/2`, and `refute_called_once/1` introduced in v0.7.0\n- [birarda](https://github.com/birarda)\n  - Suggested `assert_any_call/2`, `refute_any_call/2` introduced in v0.2.0\n  - Suggested `listen/1` introduced in v0.13.0 to listen without a target.\n- [kianmeng](https://github.com/kianmeng)\n  - Corrected several typographical errata\n  - Improved the ci.yml, brining it up to date with best practices.\n- [Dorgan](https://github.com/doorgan)\n  - Reported erratum in the Patch Cheatsheet\n- [Luca Corti](https://github.com/lucacorti)\n  - Reported an issue with warning being emitted by the library on Elixir 1.16 which served as the basis for a bugfix in v0.13.1\n- [Steve Cohen](https://github.com/scohen)\n  - Reported an issue with incorrect export handling which served as the basis for a bugfix in v0.16.0\n\nIf you have a suggestion for improvements to this library, please open an issue.\n\n## Changelog\n\nSee the [Changelog](CHANGELOG.md)","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fihumanable%2Fpatch","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fihumanable%2Fpatch","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fihumanable%2Fpatch/lists"}