{"id":19293955,"url":"https://github.com/igrishaev/mockery","last_synced_at":"2025-04-22T07:32:32.882Z","repository":{"id":29233131,"uuid":"86304016","full_name":"igrishaev/mockery","owner":"igrishaev","description":"Clojure mocking library","archived":false,"fork":false,"pushed_at":"2022-06-22T13:46:38.000Z","size":51,"stargazers_count":50,"open_issues_count":3,"forks_count":3,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-04-18T08:20:07.977Z","etag":null,"topics":["clojure","mock","testing"],"latest_commit_sha":null,"homepage":"http://grishaev.me/mockery","language":"Clojure","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"epl-1.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/igrishaev.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}},"created_at":"2017-03-27T07:25:23.000Z","updated_at":"2025-02-25T11:35:40.000Z","dependencies_parsed_at":"2022-08-19T19:10:14.405Z","dependency_job_id":null,"html_url":"https://github.com/igrishaev/mockery","commit_stats":null,"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/igrishaev%2Fmockery","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/igrishaev%2Fmockery/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/igrishaev%2Fmockery/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/igrishaev%2Fmockery/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/igrishaev","download_url":"https://codeload.github.com/igrishaev/mockery/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250195054,"owners_count":21390230,"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":["clojure","mock","testing"],"created_at":"2024-11-09T22:36:40.632Z","updated_at":"2025-04-22T07:32:32.620Z","avatar_url":"https://github.com/igrishaev.png","language":"Clojure","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Mockery\n\n[url-mock-2]:http://www.voidspace.org.uk/python/mock/\n[url-ivan]:http://grishaev.me/\n[url-foord]:http://www.voidspace.org.uk/python/weblog/index.shtml\n[url-redefs]:https://clojuredocs.org/clojure.core/with-redefs-fn\n[url-sling]:https://github.com/scgilardi/slingshot\n[url-docs]:http://grishaev.me/mockery/\n[url-tests]:https://github.com/igrishaev/mockery/blob/master/test/mockery/core_test.clj\n\nMockery is a simple and lightweight library to mock Clojure functions. It is\ninspired by Python's [mock tool][url-mock-2] initially written\nby [Michael Foord][url-foord].\n\n## Installation\n\nAdd it to your dependencies:\n\n`[mockery \"0.1.4\"]`\n\nMockery is used mostly for unit tests so it's better to put it into the `:test`\nproject's profile but not the global one.\n\n## Why?\n\nImagine you have a function that fetches data from any remote service, say\nGoogle or Twitter. On your dev machine, you don't have valid credentials or even\ncannot access a service due to network configuration.\n\nHow to write tests for such code? Moreover, how to ensure you application\nhandles an incorrect HTTP response?\n\n```\nHTTP/1.1 403 OK\n\n{\"error\": \"wrong credentials\"}\n```\n\nOr even non-JSON data (standard Nginx page):\n\n```\nHTTP/1.1 504 Gateway Timeout\n\n\u003chtml\u003e\u003cbody\u003e\u003cp\u003eGateway Timeout\u003c/p\u003e\u003c/body\u003e\u003c/html\u003e\n```\n\nWill your application deal with such a response properly without crushing with\n500 error? If you think it will, how could you guarantee that?\n\nNow imagine you have modern micro-service architecture where each action\nrequires collecting data across 3 internal web-services making API calls and to\ncompose a final result.\n\nMockery helps to imitate such unusual behaviour and write unit tests that cover\nall the cases were mentioned.\n\n## Example\n\nMockery provides a `with-mock` macros. It substitutes a function with a\ntemporary one while the code block is being executed. Inside the code block, you\nmay call that function without performing unwanted I/O.\n\nUnder the hood, it relies on the standard\nClojure [clojure.core/with-redefs-fn][url-redefs] function. The changes are\nvisible across all the threads while macros works.\n\nQuick example:\n\n```clojure\n(with-mock mock\n  {:target ::test-fn ;; your function to mock\n   :return 42}       ;; the result\n  (test-fn 1 2 3))   ;; will return 42\n```\n\nThe first parameter, `mock` in our example, is a variable name to bind a mock\nobject to. The second one is a map of options. The `:target` is the only\nrequired key that should be a full-qualified keyword or symbol. For example,\n`:clojure.string/join` or `'clojure.string/join`. If you'd like to point a\nfunction located at the same namespace, use double colon syntax as well:\n`::my-func` (expands into something like `:your.current.ns/my-func`).\n\n## Features\n\nMockery works with the built-tin unit test framework as well:\n\n```clojure\n(defn mock-google [f]\n  (with-mock _\n    {:target :some.project/get-geo-point ;; makes API call to Google\n     :return {:lat 14.2345235\n              :lng 52.523513}} ;; what your function should return instead\n    (f)))\n\n(use-fixtures\n  :each\n  mock-google)\n\n(deftest ...)\n```\n\nDuring the test, every `(get-geo-point ...)` call will return just the data you\nspecified without network communication.\n\n`:return` value could be a function that will be called to produce further\nresult.\n\n\n```clojure\n(with-mock _\n  {:target :myapp.google/get-geo-point\n   :return (fn [\u0026 _] 100500)}\n  (myapp.google/get-geo-point)) ;; returns 100500\n```\n\nThe library imitates throwing bith Java and [Slingshot][url-sling] exceptions:\n\n```clojure\n\n(with-mock mock\n  {:target ::test-fn\n   :throw (Exception. \"boom\")}\n  (try\n    (test-fn 1)\n    (catch Exception e\n      (println e)))) ;; it was thrown\n\n(with-mock mock\n  {:target ::test-fn\n   :throw {:type :domain/error ;; slingshot map\n           :data \"boom\"}}\n  (try+\n   (test-fn 1)\n   (catch [:type :domain/error] data\n     (println data)))) ;; process data map here\n```\n\nAdd side effects (prints, logs) passing a `:side-effect` key with a function\nwithout arguments:\n\n```clojure\n(with-mock mock\n   {:target ::my-func\n    :return 42\n    :side-effect #(println \"Hello!\")}\n   (my-func 1))\n;; in addition to the result, \"Hello!\" will appear.\n```\n\nMockery helps to ensure the function was called the exact number of times with\nproper arguments. The `mock` atom holds a state that changes while you call the\nmocked function. It accumulates its arguments and the number of calls:\n\n```clojure\n(with-mock mock\n  {:target ::test-fn\n   :return 42}\n  (test-fn 1)\n  (test-fn 1 2)\n  (test-fn 1 2 3)\n  @mock)\n\n;; returns (some fields are skipped)\n\n{:called? true\n :call-count 3\n :call-args '(1 2 3)                  ;; the last args\n :call-args-list '[(1) (1 2) (1 2 3)] ;; args history\n\n :return 42                           ;; the last result\n :return-list [42 42 42]              ;; the entire result history\n}\n ```\n\nYou may mock multiple functions at once using `with-mocks` macro:\n\n```clojure\n(with-mocks\n [foo {:target ::test-fn}\n  bar {:target ::test-fn-2}]\n (test-fn 1)\n (test-fn-2 1 2)\n (is (= @foo\n        {:called? true\n         :call-count 1\n         :call-args '(1)\n         :call-args-list '[(1)]\n         :target ::test-fn}))\n (is (= @bar\n        {:called? true\n         :call-count 1\n         :call-args '(1 2)\n         :call-args-list '[(1 2)]\n         :target ::test-fn-2})))\n```\n\n## Other\n\nFor further reading, check out [Mockery documentation][url-docs]\nand [unit tests][url-tests]. Feel free to submit your issues/suggestions.\n\nMockery was written by [Ivan Grishaev][url-ivan], 2018.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Figrishaev%2Fmockery","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Figrishaev%2Fmockery","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Figrishaev%2Fmockery/lists"}