{"id":19140070,"url":"https://github.com/circleci/bond","last_synced_at":"2025-05-15T11:09:07.757Z","repository":{"id":2763551,"uuid":"3761799","full_name":"circleci/bond","owner":"circleci","description":"spying for tests","archived":false,"fork":false,"pushed_at":"2025-04-14T12:16:36.000Z","size":129,"stargazers_count":128,"open_issues_count":5,"forks_count":28,"subscribers_count":104,"default_branch":"main","last_synced_at":"2025-04-14T19:59:02.135Z","etag":null,"topics":["clojure","testing"],"latest_commit_sha":null,"homepage":"","language":"Clojure","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":"stefanjudis/perf-tooling","license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/circleci.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":"CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2012-03-19T08:23:04.000Z","updated_at":"2025-04-14T12:16:15.000Z","dependencies_parsed_at":"2024-06-19T16:34:54.975Z","dependency_job_id":"e5a7f043-3407-4e1c-9d5f-f5f7af331886","html_url":"https://github.com/circleci/bond","commit_stats":{"total_commits":99,"total_committers":25,"mean_commits":3.96,"dds":0.7676767676767677,"last_synced_commit":"1413bbfbcd2ef4006528f631d6f087d4811da8bf"},"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/circleci%2Fbond","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/circleci%2Fbond/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/circleci%2Fbond/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/circleci%2Fbond/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/circleci","download_url":"https://codeload.github.com/circleci/bond/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254264731,"owners_count":22041789,"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","testing"],"created_at":"2024-11-09T07:16:09.433Z","updated_at":"2025-05-15T11:09:07.734Z","avatar_url":"https://github.com/circleci.png","language":"Clojure","funding_links":[],"categories":["Clojure"],"sub_categories":[],"readme":"Bond [![CircleCI Status](https://circleci.com/gh/circleci/bond.png?style=badge)](https://circleci.com/gh/circleci/bond)\n====\n\nBond is a spying and stubbing library, primarily intended for tests.\n\n```clojure\n[circleci/bond \"0.6.0\"]\n```\n\n```clojure\n\n(ns test.foo\n  (:require [bond.james :as bond :refer [with-spy]]))\n\n(defn foo [x]\n  (let [shaken (with-out-str (prn :martini))]\n    [shaken])\n\n(defn bar [y]\n  (foo y))\n\n(deftest foo-is-called\n  (with-spy [foo]\n    (bar 2)\n    (is (= 1 (-\u003e foo bond/calls count)))))\n```\n\nBond provides one main macro, `with-spy`. It takes a vector of defn vars (vars that resolve to fns). Each var will be redefined for the scope of the macro, wrapping the function to track arguments and call counts. At any point during the scope, you can call `(bond/calls f)`, where `f` is a spied fn. `calls` returns a seq of maps, one for each call to `f`. Each map contains the keys `:args`, a seq of args the fn was called with, and one of `:return` or `:throw`.\n\nBond also provides `with-stub!`. It works the same as `with-spy`, but redefines the function to return `(constantly nil)` (default), while also spying on it. This is generally preferable to Clojure's built-in `with-redefs` macro since it will throw an exception if the mocked function is called with the wrong number of arguments. You can specify an arbitrary function instead of the default `(constantly nil)` by providing a `[fn-var replacement-fn]` vector in place of just the fn name:\n\n```clojure\n(ns test.foo\n  (:require [bond.james :as bond :refer [with-stub!]]))\n\n(defn foo [x] ...)\n\n(defn bar [y] ...)\n\n(deftest foo-is-called\n  (with-stub! [[foo (fn [x] \"foo\")]\n               [bar (fn [y] \"bar\")]]\n    (is (= [\"foo\" \"bar\"] [(foo 1) (bar 2)]))))\n\n(deftest consecutive-stubbing\n  (with-stub! [[foo [(fn [x] \"foo1\")\n                     (fn [x] \"foo2\")\n                     (fn [x] \"foo3\")]]\n               [bar (fn [y] \"bar\")]]\n    (is (= [\"foo1\" \"foo2\" \"foo3\" \"bar\"] [(foo 1) (foo 1) (foo 1) (bar 2)]))))\n\n```\n\nPrivate functions can also be stubbed or spyed:\n\n``` clojure\n(ns test.foo)\n\n(defn- foo [x] ...)\n```\n\n``` clojure\n(ns test.bar\n  (:require [bond.james :as bond :refer [with-stub!]]\n            [test.foo :as foo]))\n\n(deftest foo-is-called\n  (with-stub! [[foo/foo (fn [x] \"foo\")]]\n    (is (= \"foo\" (#'foo/foo 1)))\n    (is (= [1] (-\u003e #'foo/foo bond/calls first :args)))))\n```\n\nThere is also a `with-stub` macro which works like `with-stub!` but omits the argument check.\n\nIn addition to `with-spy` and `with-stub!`, Bond also provides `with-spy-ns`\nand `with-stub-ns` which can spy/stub every function in a namespace in one go:\n\n```clojure\n(ns test.foo\n  (:require [bond.james :as bond]\n            [clojure.test :refer (deftest is)]))\n\n(defn foo [] :foo)\n\n(defn bar [] :bar)\n\n(deftest you-can-stub-entire-ns\n  (is (= :foo (foo)))\n  (is (= :bar (bar)))\n  (bond/with-stub-ns [[foo (constantly :baz)]]\n    (is (= :baz (foo)))\n    (is (= :baz (bar)))))\n```\n\nReleasing\n---------\n\nNew git tags are automatically published to [clojars](https://clojars.org/circleci/bond).\n\nThe following should be updated on the `main` branch before tagging:\n\n- `project.clj` - version\n- `README.md` - dependency coordinates\n- `CHANGELOG.md` - summary of changes\n\nLicense\n-------\n\nDistributed under the [Eclipse Public License](http://www.eclipse.org/legal/epl-v10.html).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcircleci%2Fbond","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcircleci%2Fbond","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcircleci%2Fbond/lists"}