{"id":15361679,"url":"https://github.com/popomore/spy","last_synced_at":"2025-04-15T08:59:49.153Z","repository":{"id":19542982,"uuid":"22791129","full_name":"popomore/spy","owner":"popomore","description":"spy and mock for simple testcase","archived":false,"fork":false,"pushed_at":"2017-04-19T12:21:51.000Z","size":26,"stargazers_count":14,"open_issues_count":0,"forks_count":4,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-04-15T08:59:44.581Z","etag":null,"topics":["mock","mocking","spy","tdd","test","testing","testing-tools","unit-testing"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/popomore.png","metadata":{"files":{"readme":"README.md","changelog":"HISTORY.md","contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2014-08-09T17:17:26.000Z","updated_at":"2023-09-06T12:23:42.000Z","dependencies_parsed_at":"2022-08-02T23:45:31.361Z","dependency_job_id":null,"html_url":"https://github.com/popomore/spy","commit_stats":null,"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/popomore%2Fspy","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/popomore%2Fspy/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/popomore%2Fspy/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/popomore%2Fspy/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/popomore","download_url":"https://codeload.github.com/popomore/spy/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":249040041,"owners_count":21202813,"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":["mock","mocking","spy","tdd","test","testing","testing-tools","unit-testing"],"created_at":"2024-10-01T12:56:12.306Z","updated_at":"2025-04-15T08:59:49.129Z","avatar_url":"https://github.com/popomore.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# spy\n\n[![NPM version](https://img.shields.io/npm/v/spy.svg?style=flat)](https://npmjs.org/package/spy)\n[![Spm version](http://spmjs.io/badge/spy)](http://spmjs.io/package/spy)\n[![Build Status](https://img.shields.io/travis/popomore/spy.svg?style=flat)](https://travis-ci.org/popomore/spy)\n[![Build Status](https://img.shields.io/coveralls/popomore/spy.svg?style=flat)](https://coveralls.io/r/popomore/spy)\n[![NPM downloads](http://img.shields.io/npm/dm/spy.svg?style=flat)](https://npmjs.org/package/spy)\n\nspy and mock for simple testcase\n\n---\n\n## Why Spy?\n\nSinon is the best spy, stub, mock lib, I use it in my every repo.\n\nBut Sinon is too big, I just use spy and simple mock, and I think it can be separated to different repo.\n\nSo I write Spy\n\n- written in commonjs, support package mananger for browser such as spm, component, bower.\n- support spy and simple mock, see API below\n\n## Install\n\n```\n$ npm install spy -g\n```\n\nInstall for browser\n\n[spm](http://spmjs.io/)\n\n```\nspm install spy\n```\n\n[component](http://component.io/)\n\n```\ncomponent install popomore/spy\n```\n\n[bower](http://bower.io/)\n\n```\nbower install spy\n```\n\n## Usage\n\n```\nvar spy = require('spy');\nvar s = spy();\ns(1);\ns.called // return true\ns.callCount // return 1\ns.calledWith(1) // return true\n```\n\nmock spy function\n\n```\nvar spy = require('spy');\nvar s = spy();\ns.mock(1);\ns(); // return 1\n```\n\nmock module\n\n```\n// a.js\nmodule.exports = function() {}\n\n// b.js\nvar a = require('spy').require('./a.js');\na();\na.callCount // return 1\n```\n\n## API\n\n### spy()\n\nCreate a anonymous `Spy` function\n\n### spy(func)\n\nCreate a `Spy` function wrapped `func`\n\n### spy(obj, 'func')\n\nCreate a `Spy` function wrapped `obj.func`\n\n### Spy\n\n`Spy` function can be used as a normal function, and it will record what the function do.\n\nBy default, Spy will pass arguments to original function, get result from the function, and use the same context;\n\nOtherwise, using `spy.mock` will call the mock function instead of calling the original function, \n\n#### spy.obj\n\nThe object that contain the refer to the function\n\n```\nspy(obj, 'a'); // obj === spy.obj\n``` \n\n#### spy.method\n\nThe original method\n\n```\nspy(obj, 'a'); // obj.a === spy.method\nspy(func); // func === spy.method\nspy(); // spy.method is an anonymous function\n```\n\n#### spy.methodName\n\nThe method name of the given function\n\n```\nspy(obj, 'a'); // 'a' === spy.method\n``` \n\n#### spy.called\n\nReturn true if the spy function has been called.\n\n#### spy.callCount\n\nReturn the count that the spy function has been called.\n\n#### spy.calls\n\nContain the call list in order, each call is the `Call` instance.\n\n```\nspy(); // spy.call[0]\nspy(); // spy.call[1]\n```\n\n#### spy.mock()\n\nMock the return value of the spy\n\n```\nspy.mock(1);\nspy(); // return 1\n```\n\nYou can do it just like a normal function\n\n```\nspy.mock(function(arg1, arg2, arg3) {\n\t// 1. return arg1\n\t// 2. return this\n\t// 3. throw new Error();\n});\n```\n\nSupport generator!!!\n\n```\nspy.mock(function* () {\n  var pkg = yield read('package.json');\n  return pkg.name;\n});\n```\n\n#### spy.reset()\n\nReset the call record and the mock method\n\n#### spy.restore()\n\nRestore the refer to the function\n\n#### spy.calledBefore / spy.calledAfter\n\nIn the call sequence, determine whether one spy is called before/after the other.\n\n```\nspy1();\nspy2();\nspy1.calledBefore(spy2); // true\nspy2.calledAfter(spy1); // true\n```\n\n#### spy.calledWith / spy.alwaysCalledWith / spy.neverCalledWith\n\nSame as call.calledWith, but will match spy.calls in diffent ways.\n\n- `spy.calledWith`, whether one of the calls called with arguments, just like\n\n  ```\n  calls.some(function(call){\n    return call.calledWith()\n  });\n  ```\n\n- `spy.alwaysCalledWith`, whether all calls called with arguments, just like\n\n  ```\n  calls.every(function(call){\n    return call.calledWith()\n  });\n  ```\n\n- `spy.neverCalledWith`, whether all calls didn't call with arguments, just like\n\n  ```\n  calls.every(function(call){\n    return !call.calledWith()\n  });\n  ```\n\n\n#### spy.calledWithNew / spy.alwaysCalledWithNew / spy.neverCalledWithNew\n\nSame as spy.calledWithNew, but will match spy.calls in diffent ways.\n\nThe different between always and never see spy.calledWith\n\n#### spy.calledWithExactly / spy.alwaysCalledWithExactly / spy.neverCalledWithExactly\n\nSame as spy.calledWithExactly, but will match spy.calls in diffent ways.\n\nThe different between always and never see spy.calledWith\n\n#### spy.calledOn / spy.alwaysCalledOn / spy.neverCalledOn\n\nSame as spy.calledOn, but will match spy.calls in diffent ways.\n\nThe different between always and never see spy.calledWith\n\n#### spy.returned / spy.alwaysReturned / spy.neverReturned\n\nSame as spy.returned, but will match spy.calls in diffent ways.\n\nThe different between always and never see spy.calledWith\n\n#### spy.threw / spy.alwaysThrew / spy.neverThrew\n\nSame as spy.threw, but will match spy.calls in diffent ways.\n\nThe different between always and never see spy.calledWith\n\n### Call\n\n`Call` object will record every function call.\n\n#### call.calledWith\n\nReturn true if match the call arguments\n\n```\nspy(1, 2, 3)\nspy.calls[0].calldWith(1) // true\nspy.calls[0].calldWith(1, 2) // true\nspy.calls[0].calldWith(1, 2, 3) // true\n```\n\n#### call.calledWithExactly\n\nSame as calledWith, but assert the arguments length\n\n```\nspy(1, 2, 3)\nspy.calls[0].calledWith(1) // false\nspy.calls[0].calledWith(1, 2) // false\nspy.calls[0].calledWith(1, 2, 3) // true\n```\n\n#### call.calledWithNew\n\nReturn true if it instantiation\n\n```\nnew spy()\nspy.calls[0].calledWithNew() // true\n```\n\n#### call.calledOn\n\nReturn true if it called with the context\n\n```\nspy.call(ctx)\nspy.calls[0].calledOn(ctx) // true\n```\n\n#### call.returned\n\nReturn true if get the matched return\n\n```\nfunction spiedFunc() { return 1; }\nvar spy = require('spy')(spiedFunc);\nspy()\nspy.calls[0].returned(1) // true\n```\n\n#### call.threw\n\nReturn true if the function had threw\n\n```\nfunction spiedFunc() { throw new Error(); }\nvar spy = require('spy')(spiedFunc);\nspy()\nspy.calls[0].threw() // true\n```\n\n## LICENSE\n\nCopyright (c) 2014 popomore. Licensed under the MIT license.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpopomore%2Fspy","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpopomore%2Fspy","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpopomore%2Fspy/lists"}