{"id":13995452,"url":"https://github.com/seanhenry/MockGenerator","last_synced_at":"2025-07-22T21:33:05.483Z","repository":{"id":43270543,"uuid":"82721733","full_name":"seanhenry/MockGenerator","owner":"seanhenry","description":"An AppCode plugin to help generate Swift test doubles automatically.","archived":false,"fork":false,"pushed_at":"2022-08-10T14:05:42.000Z","size":29085,"stargazers_count":71,"open_issues_count":1,"forks_count":11,"subscribers_count":6,"default_branch":"master","last_synced_at":"2024-12-06T22:27:35.299Z","etag":null,"topics":["appcode","appcode-plugin","mock","stub","swift","testing"],"latest_commit_sha":null,"homepage":"","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/seanhenry.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}},"created_at":"2017-02-21T20:03:09.000Z","updated_at":"2024-05-09T08:14:08.000Z","dependencies_parsed_at":"2022-08-12T10:21:34.515Z","dependency_job_id":null,"html_url":"https://github.com/seanhenry/MockGenerator","commit_stats":null,"previous_names":[],"tags_count":26,"template":false,"template_full_name":null,"purl":"pkg:github/seanhenry/MockGenerator","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/seanhenry%2FMockGenerator","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/seanhenry%2FMockGenerator/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/seanhenry%2FMockGenerator/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/seanhenry%2FMockGenerator/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/seanhenry","download_url":"https://codeload.github.com/seanhenry/MockGenerator/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/seanhenry%2FMockGenerator/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":266578638,"owners_count":23951148,"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","status":"online","status_checked_at":"2025-07-22T02:00:09.085Z","response_time":66,"last_error":null,"robots_txt_status":null,"robots_txt_updated_at":null,"robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["appcode","appcode-plugin","mock","stub","swift","testing"],"created_at":"2024-08-09T14:03:25.069Z","updated_at":"2025-07-22T21:33:04.811Z","avatar_url":"https://github.com/seanhenry.png","language":"Swift","readme":"\u003e ⚠️ This plugin is no longer being actively worked on as the author is no longer writing much Swift. Updating AppCode can cause breaking changes from time to time so feel free to raise an issue or make a pull request and I will try to fix the problem. Thank you everyone for your support!\n\n# Swift Mock Generator for AppCode\n\nAn AppCode plugin to generate spy, stub and dummy classes automatically. \n\n![AppCode plugin generates Swift spy](readme/MockGenerator.gif \"AppCode plugin generates Swift mock\")\n\n[Looking for the Xcode version?](https://github.com/seanhenry/SwiftMockGeneratorForXcode)\n\n## Install Swift Mock Generator for AppCode\n\n- Open AppCode\n- Open AppCode → Preferences `⌘,`\n- Go to Plugins\n- Click Browse repositories...\n- Search for 'Swift Mock Generator for AppCode'\n- Click Install\n- Restart AppCode\n\n## How to create a new Swift test double\n\nYou can generate a spy, stub or dummy. [See here](https://martinfowler.com/bliki/TestDouble.html) for more information around test double nomenclature.\n\n- Create an empty class conforming to one or many protocols and/or a class.\n- With the cursor inside the class declaration, press `⌥↵`.\n- Select 'Generate spy|stub|dummy|partial spy'.\n\n## How to recreate a Swift test double\n\nIf you change the underlying protocol its test double will need to be regenerated.  \n\nTo regenerate the test double, place the cursor anywhere inside the test double and select ‘Generate spy|stub|dummy’ again.\n\n## Features\n\n| Feature                                                                                              | Supported         |\n|------------------------------------------------------------------------------------------------------|-------------------|\n| Generate and regenerate a spy.                                                                       | ✅                 |\n| Generate and regenerate a stub.                                                                      | ✅                 |\n| Generate and regenerate a dummy.                                                                     | ✅                 |\n| Generate and regenerate a partial spy (forwards invocations to original implementation if required). | ✅                 |\n| **Classes and protocols**                                                                            |\n| Generates test doubles conforming to one or many protocols.                                          | ✅                 |\n| Generates test doubles conforming to a class.                                                        | ✅                 |\n| Generates test doubles conforming to both classes and protocols.                                     | ✅                 |\n| **Recording methods and properties**                                                                 |\n| Captures invocation status of methods.                                                               | ✅                 |\n| Captures invocation status of properties.                                                            | ✅                 |\n| Records multiple invocations of methods.                                                             | ✅                 |\n| Records multiple invocations of properties.                                                          | ✅                 |\n| Captures invoked method parameters.                                                                  | ✅                 |\n| Records multiple invocations of method parameters.                                                   | ✅                 |\n| Supports multiple properties in the same declaration.                                                | ✅                 |\n| **Stubbing return values and closures**                                                              |\n| Stubs values for your test doubles to return.                                                        | ✅                 |\n| Stubs a default value for return values where possible.                                              | ✅                 |\n| Automatically calls closure parameters with stubbed values.                                          | ✅                 |\n| **Initializers**                                                                                     |\n| Generates convenience initializers requiring no parameters.                                          | ✅                 |\n| Supports initializers with arguments.                                                                | ✅                 |\n| Supports failable initializers.                                                                      | ✅                 |\n| Supports required initializers.                                                                      | ✅                 |\n| **Throws**                                                                                           |\n| Stub an error for your overridden method to throw.                                                   | ✅                 |\n| Supports throwing initializers.                                                                      | ✅                 |\n| Supports throwing closures.                                                                          | ✅                 |\n| **Generics**                                                                                         |\n| Generates generic test doubles from protocols with associated types.                                 | ✅                 |\n| Captures invoked generic parameters.                                                                 | ✅                 |\n| Captures invoked generic return values.                                                              | ✅                 |\n| **Scope, keywords, and more**                                                                        |\n| Avoids naming clashes from overloaded methods.                                                       | ✅                 |\n| Supports parameter type-annotation attributes and `inout`.                                           | ✅                 |\n| Respects the test double scope and generates `public` and `open` methods and properties.             | ✅(protocols only) |\n| Generate test doubles inheriting from items in 3rd party frameworks.                                 | ✅(protocols only) |\n\n## Usage example\n\nA protocol called Animator that we wish to spy on:\n\n```\nprotocol Animator {\n  func animate(duration: TimeInterval, animations: () -\u003e (), completion: (Bool) -\u003e ()) -\u003e Bool\n}\n```\nCreate a spy class conforming to a protocol:\n```\nclass AnimatorSpy: Animator {\n}\n```\nGenerate the spy:\n\n```\nclass AnimatorSpy: Animator {\n\n  var invokedAnimate = false\n  var invokedAnimateCount = 0\n  var invokedAnimateParameters: (duration: TimeInterval, Void)?\n  var invokedAnimateParametersList = [(duration: TimeInterval, Void)]()\n  var shouldInvokeAnimateAnimations = false\n  var stubbedAnimateCompletionResult: (Bool, Void)?\n  var stubbedAnimateResult: Bool! = false\n\n  func animate(duration: TimeInterval, animations: () -\u003e (), completion: (Bool) -\u003e ()) -\u003e Bool {\n    invokedAnimate = true\n    invokedAnimateCount += 1\n    invokedAnimateParameters = (duration, ())\n    invokedAnimateParametersList.append((duration, ()))\n    if shouldInvokeAnimateAnimations {\n      animations()\n    }\n    if let result = stubbedAnimateCompletionResult {\n      completion(result.0)\n    }\n    return stubbedAnimateResult\n  }\n}\n```\nInject the spy into the class you wish to test:\n\n```\nlet animatorSpy = AnimatorSpy()\nlet object = ObjectToTest(animator: animatorSpy)\n```\nTest if animate method was invoked:\n\n```\nfunc test_spyCanVerifyInvokedMethod() {\n  object.myMethod()\n  XCTAssertTrue(animatorSpy.invokedAnimate)\n}\n```\nTest the correct parameter was passed to the animate method:\n\n```\nfunc test_spyCanVerifyInvokedParameters() {\n  object.myMethod()\n  XCTAssertEqual(animatorSpy.invokedAnimateParameters?.duration, 5)\n}\n```\nTest the number of times animate was invoked:\n\n```\nfunc test_spyCanVerifyInvokedMethodCount() {\n  object.myMethod()\n  object.myMethod()\n  XCTAssertEqual(animatorSpy.invokedAnimateCount, 2)\n}\n```\nTest the parameters passed into each call of the animate method:\n\n```\nfunc test_spyCanVerifyMultipleInvokedMethodParameters() {\n  object.myMethod()\n  object.myMethod()\n  XCTAssertEqual(animatorSpy.invokedAnimateParametersList[0].duration, 5)\n  XCTAssertEqual(animatorSpy.invokedAnimateParametersList[1].duration, 5)\n}\n```\nStub a return value for the animate method:\n\n```\nfunc test_spyCanReturnAStubbedValue() {\n  animatorSpy.stubbedAnimateResult = true\n  let result = object.myMethod()\n  XCTAssertTrue(result)\n}\n```\nStub the value for the completion closure in the animate method:\n\n```\nfunc test_spyCanCallClosure_withStubbedValue() {\n  animatorSpy.stubbedAnimateCompletionResult = (false, ())\n  object.myMethod()\n  XCTAssertFalse(object.animationDidComplete)\n}\n```\n\n## Nomenclature\n\nDespite being called a Mock Generator, this plugin actually generates a spy, stub or dummy. The word 'mock', whilst not technically correct, has been used because test doubles such as spies, mocks, and stubs have become commonly known as mocks.\n\n## Build\n\nIf you would like to try building the plugin yourself follow these steps.\n\n- Open `build.gradle`\n- Change `intellij.localPath` and `runIde.ideDirectory` to the path of your AppCode app\n- Run `./gradlew runIde`\n","funding_links":[],"categories":["Swift"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fseanhenry%2FMockGenerator","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fseanhenry%2FMockGenerator","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fseanhenry%2FMockGenerator/lists"}