{"id":13772545,"url":"https://github.com/dionisiydk/Mocketry","last_synced_at":"2025-05-11T04:31:32.422Z","repository":{"id":22763851,"uuid":"97255575","full_name":"dionisiydk/Mocketry","owner":"dionisiydk","description":"Mock objects framework","archived":false,"fork":false,"pushed_at":"2024-03-29T22:36:32.000Z","size":366,"stargazers_count":18,"open_issues_count":1,"forks_count":9,"subscribers_count":4,"default_branch":"master","last_synced_at":"2024-03-29T23:30:40.925Z","etag":null,"topics":["bdd","mocketry","mocks","pharo","sunit","tdd"],"latest_commit_sha":null,"homepage":null,"language":"Smalltalk","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/dionisiydk.png","metadata":{"files":{"readme":"README.md","changelog":null,"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-07-14T16:57:54.000Z","updated_at":"2024-08-03T17:06:09.308Z","dependencies_parsed_at":"2024-08-03T17:16:05.016Z","dependency_job_id":null,"html_url":"https://github.com/dionisiydk/Mocketry","commit_stats":null,"previous_names":[],"tags_count":18,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dionisiydk%2FMocketry","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dionisiydk%2FMocketry/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dionisiydk%2FMocketry/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dionisiydk%2FMocketry/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dionisiydk","download_url":"https://codeload.github.com/dionisiydk/Mocketry/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253518941,"owners_count":21921074,"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":["bdd","mocketry","mocks","pharo","sunit","tdd"],"created_at":"2024-08-03T17:01:05.190Z","updated_at":"2025-05-11T04:31:27.400Z","avatar_url":"https://github.com/dionisiydk.png","language":"Smalltalk","funding_links":[],"categories":["Testing"],"sub_categories":[],"readme":"# Mocketry\n\n[![GitHub release](https://img.shields.io/github/release/dionisiydk/Mocketry.svg)](https://github.com/dionisiydk/Mocketry/releases/latest)\n[![Unit Tests](https://github.com/dionisiydk/Mocketry/actions/workflows/tests.yml/badge.svg)](https://github.com/dionisiydk/Mocketry/actions/workflows/tests.yml)\n\n[![Pharo 7.0](https://img.shields.io/badge/Pharo-7.0-informational)](https://pharo.org)\n[![Pharo 8.0](https://img.shields.io/badge/Pharo-8.0-informational)](https://pharo.org)\n[![Pharo 9.0](https://img.shields.io/badge/Pharo-9.0-informational)](https://pharo.org)\n[![Pharo 10](https://img.shields.io/badge/Pharo-10-informational)](https://pharo.org)\n[![Pharo 11](https://img.shields.io/badge/Pharo-11-informational)](https://pharo.org)\n[![Pharo 11](https://img.shields.io/badge/Pharo-12-informational)](https://pharo.org)\n\nMocketry is mock objects framework\\. It provides simplest way to stub any message to any object and to verify any occurred behaviour\n\n## Installation\nUse following script for Pharo version \u003e= 6:\n```Smalltalk\nMetacello new\n  baseline: 'Mocketry';\n  repository: 'github://dionisiydk/Mocketry';\n  load\n```\nTo add dependency in your project baseline:\n```Smalltalk\nspec\n    baseline: 'Mocketry'\n    with: [ spec repository: 'github://dionisiydk/Mocketry:versionTagOrBranch' ]\n```\nFor old Pharo versions project should be loaded from smalltalkhub:\n```Smalltalk\nMetacello new\n      smalltalkhubUser: 'dionisiy' project: 'Mocketry';\n      configuration: 'Mocketry';\n      version: #stable;\n      load.\n```\n## Create mocks easily\nTo create mock just use **\\#new**\n```Smalltalk\nyourMock := Mock new.\n```\nMocketry not requires any special context variables for this\\.\n\nAlso Mocketry implements auto naming logic to retrive variable names from test context\\. Inside test yourMock will be shown as \"a Mock\\(yourMock\\)\" \\(in debugger\\)\\.\n\nBut if you need special name you can specify it:\n```Smalltalk\nMock named: 'yourMock'\n```\nYou can look at it livelly in MockTests\\.\n\nAlso there is way to get multiple mocks at once:\n```Smalltalk\n[ :mockA :mockB | \"your code here\" ] runWithMocks\n```\n## Stub any message sends\n\u003ca name=\"stubMessageSends\"\u003e\u003c/a\u003eTo stub message send just send message **\\#stub** to object and following message will create expectation:\n```Smalltalk\nmock := Mock new.\n    \nmock stub someMessage willReturn: 100.\n    \nmock someMessage should be: 100.\n```\nYou can stub any objects\\. It is not only about mocks:\n```Smalltalk\nrect := 0@0 corner: 2@3.\n    \nrect stub width willReturn: 1000.\n    \nrect area should be: 3000 \"are = width * height\"\n```\nAnd you can do this with globals too:\n```Smalltalk\nDateAndTime stub now willReturn: #constantValue.\n    \nDateAndTime now should be: #constantValue.\n```\nBut you should be carefull with globals\\. Don't try\n```Smalltalk\nArray stub new.\n```\nIt will crash image\\.\nAnd if you stub global from workspace it is your responsibility to recover it from stub behaviour\\. Do it by this:\n```Smalltalk\nDateAndTime recoverFromGHMutation.\n```\nIn case when you stub global inside test Mocketry automatically recovers all global stubs when test completes\\.\n\nAlso with Mocketry you can define expectations for set of objects\\. For example you can stub message to **ANY object**:\n```Smalltalk\nAny stub width willReturn: 100.\n    \nmock := Mock new.\nmock width should be: 100.\n    \nrect := 0@0 corner: 2@3.\nrect stub. \"#stub activates message intercection for real object. Without it following sentence will not work\"\n    \nrect area should be: 300.\n```\nOr you can stub **ANY message** to particular object:\n```Smalltalk\nmock := Mock new.\n    \nmock stub anyMessage willReturn: 100.\n    \nmock someMessage should be: 100.\nmock someMessage2 should be: 100.\n```\nAnd both variants are supported:\n```Smalltalk\nAny stub anyMessage willReturn: 100.\n    \nmock := Mock new.\nmock someMessage should be: 100.\n    \nrect := 0@0 corner: 2@3.\nrect stub.\n    \nrect area should be: 100.\nrect width should be: 100.\n```\n**Any** class is specific object spec which means \"any\" object\\. You can uses any kind of specs:\n```Smalltalk\n(Kind of: Rectangle) stub width willReturn: 100.\n    \nrect := 0@0 corner: 2@3.\nrect stub.\n    \nrect area should be: 300.\n    \nrect2 := 0@0 corner: 4@5.\nrect2 stub.\n    \nrect2 area should be: 500\n```\n### Stub message sends with arguments\nIn place of message arguments you can use expected objects itself\\. Or you can put specifications for expected arguments:\n```Smalltalk\nmock stub messageWith: arg1 and: arg2\nmock stub messageWith: Any and: arg2\nmock stub messageWith: [:arg | true]\nmock stub messageWith: (Kind of: String) and: arg2\nmock stub messageWith: (Instance of: Float) \u0026 (Satisfying for: [:arg | arg \u003e 10]).\n```\nLast defined expectation has more priority than previous one\\. It allows you to define default expectations in setUp method and override it in particular tests\\. Following example shows it:\n```Smalltalk\nmock := Mock new.\n(mock stub messageWith: (Instance of: SmallInteger)) willReturn: #anyInt.\n(mock stub messageWith: (Kind of: String)) willReturn: #anyString.\n(mock stub messageWith: 10) willReturn: #ten.\n    \n(mock messageWith: 10) should be: #ten.\n(mock messageWith: 20) should be: #anyInt.\n(mock messageWith: 'test') should be: #anyString\n```\n### Expected actions for stubs\nThere are different kind of expected actions:\n```Smalltalk\nmock := Mock new.\n    \nmock stub someMessage willReturn: #result.\nmock someMessage should be: #result.\n    \nmock stub someMessage willRaise: ZeroDivide new.\n[mock someMessage] should raise: ZeroDivide.\n    \n(mock stub someMessageWith: #arg) will: [#result].\n(mock someMessageWith: #arg) should be: #result.\n    \n(mock stub someMessageWith: #arg1 and: #arg2) will: [:arg1 :arg2 | arg1, arg2].\n(mock someMessageWith: #arg1 and: #arg2) should equal: 'arg1arg2'.\n    \nmock stub someMessage willReturnValueFrom: #(result1 result2).\nmock someMessage should be: #result1.\nmock someMessage should be: #result2\n```\n### Extra conditions on message sends\nIt is possible to verify arbitrary condition when expected message is going to be executed\\. For example:\n```Smalltalk\nmock := Mock new.\nmock stub someMessage\n    when: [flag] is: (Kind of: Boolean);\n    when: [flag] is: true;\n    when: [ flag ] satisfy: [ :object | true or: [ false ] ].\n    \nflag := true.\nmock someMessage. \"not failes\"\n    \nflag := false.\nmock someMessage \"will fail immediately on call by last condition: flag should be true\"\n    \nflag := #flag.\nmock someMessage \"will fail immediately on call by first condition: flag should be boolean\"\n```\nAlso Mocketry implements process related condition to check that message was synchronously sent \\(relative to test process\\):\n```Smalltalk\nmock stub someMessage shouldBeSentInThisProcess.\n[ mock someMessage ] fork. \"will fail immediately on call\".\n    \nmock stub someMessage shouldBeSentInAnotherProcess.\n[ mock someMessage ] fork. \"will not fail\".\nmock someMessage. \"will fail immediately on call\"\n```\n### Message sends usage rules\nIt is possible to specify how much times expectation can be used:\n```Smalltalk\nmock := Mock new.\n    \nmock stub someMesage willReturn: #default.\nmock stub someMessage willReturn: 300; use: 3.\nmock stub someMessage willReturn: 200; useTwice.\nmock stub someMesage willReturn: 100 useOnce.\n    \n\"last defined expectation is more preferred then previously defined\"\nmock someMessage should be: 100.\n    \nmock someMessage should be: 200.\nmock someMessage should be: 200.\n    \nmock someMessage should be: 300.\nmock someMessage should be: 300.\nmock someMessage should be: 300.\n    \nmock someMessage should be: #default\n```\n### Unexpected messages\\. Automocks\nMock returns another special mock for unexpected messages \\(when no expectation is defined for received message\\):\n```Smalltalk\nmock := Mock new.\n    \nautomock := mock someMessage.\n    \nautomock should beInstanceOf: MockForMessageReturn.\n```\nAnd any message to this mock will produce another automock\\.\nIt means that your tests will not fail if you will not define any expectation for your mocks\\.\nIt allows you put only required detailes inside your tests which really make sense for tested aspect of functionality\\. Anything else does not matters\\.\n\nAlso to improve this idea automock try to play role of false in boolean expressions\\.\n```Smalltalk\nmock := Mock new.\nreturnedMock := mock someMessage.\n    \nresult := returnedMock ifFalse: [ #falseBranch ] ifTrue: [ #trueBranch ].\n    \nresult should be: #falseBranch.\nreturnedMock should be: false\n```\nAnd play zero in arithmetic\n```Smalltalk\nmock := Mock new.\nreturnedMock := mock someMessage.\n    \nresult := 1 + returnedMock.\nresult should equal: 1.\nreturnedMock should equal: 0\n```\n### Stub group of message sends\nThere is way to stub multiple message sends at once:\n```Smalltalk\nmock := Mock new.\nrect := 0@0 corner: 2@3.\nrect stub.\n    \n[ mock someMessage willReturn: 10.\nrect width willReturn: 1000 ] should expect.\n    \nmock someMessage should be: 10.\nrect area should be: 3000.\n```\nInside \"should expect\" block you don't need to send **extra \\#stub** message to objects\n\n## Verify message sends\n\nWith Mocketry you can check that particular object received particular message\\. Use **\"should receive**\" expression for this:\n```Smalltalk\nmock := Mock new.\n    \nmock someMessage.\n    \nmock should receive someMessage.\nmock should not receive anotherMessage\n```\nYou can verify that message was send to real objects\\. It is not only about mocks:\n```Smalltalk\nrect := 0@0 corner: 2@3.\n    \nrect stub \"it should be here to enable message interception\"\nrect area\n    \nrect should receive width. \"area = width * height\"\n```\nAnd you can do this with globals too:\n```Smalltalk\nDateAndTime stub.\nDateAndTime midnight.\n    \nDateAndTime should receive now. \"inside midnight #now is called\"\n```\nBut you should be carefull with globals\\. Look at section [¿?](#stubMessageSends)\\.\n\nAlso with Mocketry you can verify that message was sent to set of objects\\.\nFor example you can verify that message was sent to **ANY object**:\n```Smalltalk\nmock := Mock new.\nrect := 0@0 corner: 2@3.\nrect stub.\n    \nmock width.\nrect area.\n    \nAny inTest should receive width. \"it will check that mock and rect received message #width\"\nAny inTest should receive area \"it will fail because mock not received #area message\".\n```\nAlso you can verify that **ANY message** was sent to particular object:\n```Smalltalk\nmock := Mock new.\n    \nmock someMessage should be: 100.\n    \nmock should receive anyMessage.\n```\nAnd both variants are supported:\n```Smalltalk\nmock := Mock new.\nrect := 0@0 corner: 2@3.\nrect stub.\n    \nmock someMessage.\n    \nAny inTest should receive anyMessage. \"will fail because rect not received any message\".\n    \nrect width.\n    \nAny inTest should receive anyMessage. \"will not fail because both objects received at least one message\"\n```\n**Any** class is specific object spec which means \"any\" object\\. You can use any kind of specs to verify message send for set of objects:\n```Smalltalk\nrect := 0@0 corner: 2@3.\nrect stub.\n    \nrect area.\n    \nrect2 := 0@0 corner: 4@5.\nrect2 width.\n    \n(Kind of: Rectangle) inTest should receive width. \"will not fail because both rect's received message #width\"\n(Kind of: Rectangle) inTest should receive area \"will fail because rect2 not received message #area\"\n    \nmock := Mock new.\n(Kind of: Rectangle) inTest should receive width. \"will not fail because mock is not kind of Rectangle\"\n```\n### Verify message sends with arguments\n\nIn place of message arguments you can use expected objects itself\\. Or you can put specifications for expected arguments:\n```Smalltalk\nmock := Mock new.\n    \nmock messageWith: 10.\nmock messageWith: 'test'.\n    \nmock should receive messageWith: 10.\nmock should receive messageWith: (Instance of: SmallInteger).\nmock should receive messageWith: 'test'.\nmock should receive messageWith: (Kind of: String).\nmock should receive messageWith: [:arg | arg isNumber].\n```\n### Capture message arguments\nMocketry provides suitable tool to capture arguments of messages for subsequent verification:\n```Smalltalk\nmock := Mock new.\nmock someMessageWith: Arg argName.\n    \nmock someMessageWith: #argValue.\n    \nArg argName should be: #argValue.\n```\nAs argument spec capture plays role of any object\\. So it does not restrict message send expectation\\. Capture will store all received argument values\\. To verify concrete argument use message \\#fromCall:\n```Smalltalk\nArg argName fromFirstCall should be: #value1.\nArg argName fromLastCall should be: #value3.\n(Arg argName fromCall: 2) should be: #value2.\nArg argName fromAllCalls should beKindOf: Symbol.\n```\nShort version:\n```Smalltalk\nArg argName should be: #argValue.\n```\nwill signal error if there are multiple different captured values\\.\n\nAlso \"should\" expression on capture will verify that owner message send was occurred required number of times\\.\n\nWhen argument is captured its value is stubbed\\. It allows you to verify subsequent message sends to captured arguments:\n```Smalltalk\nmock stub someMessageWith: Arg rectangle.\n    \nrect := 0@0 corner: 2@3.\nmock someMessageWith: rect.\nrect area.\n    \nArg rectangle should be: rect.\nArg rectangle should receive width.\n```\n### Verify message sends count\n\nMocketry allows to verify how many times object received particular message:\n```Smalltalk\nmock := Mock new.\n    \nmock someMessage.\nmock should receive someMessage once.\n    \nmock someMessage.\nmock should receive someMessage twice.\n    \nmock someMessage.\nmock should receive someMessage exactly: 3.\nmock should receive someMessage atLeast: 2.\nmock should receive someMessage atMost: 3.\nmock should receive someMessage atLeast: 1 atMost: 5.\n```\nSame works to verify that set of objects received particular message expected number of times:\n```Smalltalk\nmock := Mock new.\nmock2 := Mock new.\n    \nmock someMessage; someMessage.\nmock2 someMessage.\n    \nAny inTest should receive someMessage twice. \"will fail because mock2 received #someMessage only once\"\n    \nmock2 someMessage.\nAny inTest should receive someMessage twice. \"will not fail because both mocks received #someMessage twice\"\n```\n### Verify message send result\nThere are two ways how to verify result of occurred message:\n\nFirst you can continue \"should receive\" expression with \"which should\" clause to validate actual returned value:\n```Smalltalk\nrect := 0@0 corner: 2@3.\nrect stub.\n    \nrect area.\n    \nrect should receive area which should equal: 6.\nrect should receive width which should beKindOf: Number\n```\nAnd you can validate sender message of any object:\n```Smalltalk\nmock := Mock new.\n    \nresult := mock someMessage.\n    \nresult should beReturnedFrom: [ mock someMessage ].\n```\n### Verify group of message sends\nThere is way to verify group of message sends at once:\n```Smalltalk\nmock := Mock new.\nrect := 0@0 corner: 2@3.\nrect stub.\n    \nmock someMessage.\nrect area.\n    \n[ rect width.\nmock someMessage ] should beDone.\n    \n[ mock someMessage.\nrect width ] should beDoneInOrder.\n```\n**\\#beDone** don't care about order of message sends\\.\n\n**\\#beDoneInOrder** verifies that messages were set in same order as they defined inside given block\n\n### Verify all expectations\nThere is way how to verify that all defined expectations were occurred:\n```Smalltalk\nmock1 := Mock new.\nmock2 := Mock new.\n    \n[mock1 someMessage. mock2 someMessage2]\n    should lenient satisfy:\n[ mock2 someMessage2.\nmock1 someMessage willReturn: 'some'].\n```\n**\\#lenient** means that we don't care about order in which expected messages were happened\\.\n```Smalltalk\nmock1 := Mock new.\nmock2 := Mock new.\n    \n[mock1 someMessage. mock2 someMessage2]\n    should strictly satisfy:\n[ mock1 someMessage willReturn: 'some'.\nmock2 someMessage2].\n```\n**\\#strictly** means that we want expected messages were happened in same order in which they were defined\\.\n\n### Verify delayed async message sends\nStateSpecs provide special expression **\\#takeAWhile** on verify future state of objects which use usefull for testing asyncronous code when synchronization in the test is not possible:\n```Smalltalk\nmock := Mock new.\n[mock someMessage] fork.\n\nmock should takeAWhile to receive someMessage.\n```\n\"Take a while\" logic is supported for any kind of should expressions described above.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdionisiydk%2FMocketry","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdionisiydk%2FMocketry","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdionisiydk%2FMocketry/lists"}