{"id":13509229,"url":"https://github.com/appunite/mockery","last_synced_at":"2025-04-05T05:08:46.289Z","repository":{"id":46633859,"uuid":"95249066","full_name":"appunite/mockery","owner":"appunite","description":"Simple mocking library for asynchronous testing in Elixir.","archived":false,"fork":false,"pushed_at":"2024-07-04T12:06:29.000Z","size":236,"stargazers_count":94,"open_issues_count":2,"forks_count":10,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-29T04:08:58.306Z","etag":null,"topics":["asynchronous-tests","elixir","elixir-lang","exunit","mock-library","mocking"],"latest_commit_sha":null,"homepage":"https://hex.pm/packages/mockery","language":"Elixir","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/appunite.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}},"created_at":"2017-06-23T19:12:11.000Z","updated_at":"2025-03-24T13:13:46.000Z","dependencies_parsed_at":"2024-11-01T09:43:39.387Z","dependency_job_id":null,"html_url":"https://github.com/appunite/mockery","commit_stats":{"total_commits":228,"total_committers":10,"mean_commits":22.8,"dds":0.06140350877192979,"last_synced_commit":"6467c3edb2095c94890ee4799da17312f162b6df"},"previous_names":[],"tags_count":22,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/appunite%2Fmockery","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/appunite%2Fmockery/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/appunite%2Fmockery/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/appunite%2Fmockery/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/appunite","download_url":"https://codeload.github.com/appunite/mockery/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247289428,"owners_count":20914464,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["asynchronous-tests","elixir","elixir-lang","exunit","mock-library","mocking"],"created_at":"2024-08-01T02:01:04.896Z","updated_at":"2025-04-05T05:08:46.268Z","avatar_url":"https://github.com/appunite.png","language":"Elixir","funding_links":[],"categories":["Testing"],"sub_categories":[],"readme":"# Mockery\n\n[![Build Status](https://github.com/appunite/mockery/workflows/Test/badge.svg?branch=master)](https://github.com/appunite/mockery/actions) [![SourceLevel](https://app.sourcelevel.io/github/appunite/-/mockery.svg)](https://app.sourcelevel.io/github/appunite/-/mockery) [![Hex.pm](https://img.shields.io/hexpm/v/mockery.svg)](https://hex.pm/packages/mockery) [![Hex.pm](https://img.shields.io/hexpm/dt/mockery.svg)](https://hex.pm/packages/mockery) [![Hex.pm](https://img.shields.io/hexpm/dw/mockery.svg)](https://hex.pm/packages/mockery)\n\nSimple mocking library for asynchronous testing in Elixir.\n\n\u003e Readme and documentation for last stable version are available on [hex](https://hexdocs.pm/mockery/readme.html)\n\n## Advantages\n\n- Mockery does not override your modules\n- Mockery does not replace modules by aliasing\n- Mockery does not require to pass modules as function parameter\n- Mockery does not require to create callbacks or wrappers around libraries\n- Mockery does not create modules during runtime (neither by `defmodule/2` nor `Module.create/3`)\n- Mockery does not allow to mock non-existent function\n- Mockery does not share any data between test processes\n\n## Disadvantages\n\n- Mockery is not designed for libraries as it would force end user to download Mockery as dependency of dependency\n- Mockery can cause issues with dialyzer if you are using dialyzer with `MIX_ENV=test`\n\n## Upgrading Erlang/OTP to 21\n\nErlang/OTP 21 contains some changes that prevent the package from functioning as before.\u003cbr\u003e\nPlease check [migration guide](MIGRATION_TO_OTP21.md).\n\n## Getting started\n\n### Installation\n\n```elixir\ndef deps do\n  [\n    {:mockery, \"~\u003e 2.3.0\", runtime: false}\n  ]\nend\n```\n\n### Preparation of the module for mocking\n\n```elixir\n# lib/my_app/foo.ex\ndefmodule MyApp.Foo do\n  use Mockery.Macro\n  alias MyApp.Bar\n\n  def baz, do: mockable(Bar).function()\nend\n```\n\n## Basic usage\n\n### Static value mock\n\n```elixir\ndefmodule MyApp.Controller do\n  # ...\n  use Mockery.Macro\n\n  def all do\n    mockable(MyApp.UserService).users()\n  end\n\n  def filtered do\n    mockable(MyApp.UserService).users(\"filter\")\n  end\nend\n\n# tests\ndefmodule MyApp.ControllerTest do\n  # ...\n  import Mockery\n\n  test \"mock any function :users from MyApp.UserService\" do\n    mock MyApp.UserService, :users, \"mock\"\n    assert all() == \"mock\"\n    assert filtered() == \"mock\"\n  end\n\n  test \"mock MyApp.UserService.users/0\" do\n    mock MyApp.UserService, [users: 0], \"mock\"\n    assert all() == \"mock\"\n    refute filtered() == \"mock\"\n  end\n\n  test \"mock MyApp.UserService.users/0 with default value\" do\n    mock MyApp.UserService, users: 0\n    assert all() == :mocked\n    refute filtered() == :mocked\n  end\n\n  test \"chaining multiple mocks for same module\" do\n    UserService\n    |\u003e mock([users: 0], \"mock value\")\n    |\u003e mock([users: 1], \"mock value\")\n    # ...\n  end\nend\n```\n\n### Dynamic mock\n\nInstead of using a static value, you can use a function with the same arity as original one.\n\n```elixir\ndefmodule Foo do\n  def bar(value), do: value\nend\n\n# prepare tested module\ndefmodule Other do\n  use Mockery.Macro\n\n  def parse(value) do\n    mockable(Foo).bar(value)\n  end\nend\n\n# tests\ndefmodule OtherTest do\n # ...\n import Mockery\n\n  test \"with dynamic mock\" do\n    mock Foo, [bar: 1], fn(value)-\u003e String.upcase(value) end\n    assert parse(\"test\") == \"TEST\"\n  end\nend\n```\n\n## Checking if function was called\n\n```elixir\n# prepare tested module\ndefmodule Tested do\n  use Mockery.Macro\n\n  def call(value, opts) do\n    mockable(Foo).bar(value)\n  end\nend\n\n# tests\ndefmodule TestedTest do\n  # ...\n  import Mockery.Assertions\n  # use Mockery # when you need to import both Mockery and Mockery.Assertions\n\n  test \"assert any function bar from module Foo was called\" do\n    Tested.call(1, %{})\n    assert_called Foo, :bar\n  end\n\n  test \"assert Foo.bar/2 was called\" do\n    Tested.call(1, %{})\n    assert_called Foo, bar: 2\n  end\n\n  test \"assert Foo.bar/2 was called with given args\" do\n    Tested.call(1, %{})\n    assert_called Foo, :bar, [1, %{}]\n  end\n\n  test \"assert Foo.bar/1 was called with given arg (using variable)\" do\n    params = %{a: 1, b: 2}\n\n    Tested.call(params)\n    assert_called Foo, :bar, [^params]\n    # we need to use pinning here since assert_called/3 is a macro\n    # and not a regular function call and it gets expanded accordingly\n  end\n\n  test \"assert Foo.bar/2 was called with 1 as first arg\" do\n    Tested.call(1, %{})\n    assert_called Foo, :bar, [1, _]\n  end\n\n  test \"assert Foo.bar/2 was called with 1 as first arg 5 times\" do\n    # ...\n    assert_called Foo, :bar, [1, _], 5\n  end\n\n  test \"assert Foo.bar/2 was called with 1 as first arg from 3 to 5 times\" do\n    # ...\n    assert_called Foo, :bar, [1, _], 3..5\n  end\n\n  test \"assert Foo.bar/2 was called with 1 as first arg 3 or 5 times\" do\n    # ...\n    assert_called Foo, :bar, [1, _], [3, 5]\n  end\nend\n```\n\n### Refute\n\nEvery assert_called/x function/macro has its refute_called/x counterpart.\u003cbr\u003e\nFor more information see [docs](https://hexdocs.pm/mockery/Mockery.Assertions.html)\n\n### History\n\n![history example](https://raw.githubusercontent.com/appunite/mockery/master/history.jpeg)\n\nMockery.History module provides more descriptive failure messages for assert_called/{3,4} and refute_called/{3,4} that includes a colorized list of arguments passed to a given function in the scope of a single test process.\n\nDisabled by default. For more information see [docs](https://hexdocs.pm/mockery/Mockery.History.html)\n\n## Global mock\n\nUseful when you need to use the same mock many times across different tests\n\n```elixir\ndefmodule Foo do\n  def bar, do: 1\n  def baz, do: 2\nend\n\ndefmodule FooGlobalMock do\n  def bar, do: :mocked\nend\n\n# prepare tested module\ndefmodule Other do\n  use Mockery.Macro\n\n  def bar, do: mockable(Foo, by: FooGlobalMock).bar()\n  def baz, do: mockable(Foo, by: FooGlobalMock).baz()\nend\n\n# tests\ndefmodule OtherTest do\n  # ...\n\n  test \"with global mock\" do\n    assert Other.bar == :mocked\n    assert Other.baz == 2\n  end\nend\n```\n\n### Restrictions\n\nGlobal mock module doesn't have to contain every function exported by the original module, but it cannot contain a function which is not exported by the original module.\u003cbr\u003e\nIt means that:\n\n- when you remove a function from the original module, you have to remove it from global mock module or Mockery will raise exception\n- when you change a function name in the original module, you have to change it in global mock module or Mockery will raise exception\n- when you change a function arity in the original module, you have to change it in global mock module or Mockery will raise exception\n\n## Advanced examples\n\nFor advanced usage examples see\n\n\u003cexamples.md\u003e\n\u003c/examples.md\u003e\n\n## External resources\n\n- \u003chttps://stephenbussey.com/2018/02/15/my-favorite-elixir-testing-tool-mockery\u003e\n\n## License\n\nCopyright 2017-2024 Tobiasz Małecki [tobiasz.malecki@appunite.com](mailto:tobiasz.malecki@appunite.com)\n\nLicensed under the Apache License, Version 2.0 (the \"License\"); you may not use this file except in compliance with the License. You may obtain a copy of the License at\n\n\u003chttp://www.apache.org/licenses/LICENSE-2.0\u003e\n\nUnless required by applicable law or agreed to in writing, software distributed under the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fappunite%2Fmockery","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fappunite%2Fmockery","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fappunite%2Fmockery/lists"}