{"id":15038810,"url":"https://github.com/curatoopensource/mock-n-stub","last_synced_at":"2025-04-09T23:54:22.275Z","repository":{"id":62447925,"uuid":"134328245","full_name":"CuratoOpenSource/Mock-N-stub","owner":"CuratoOpenSource","description":"Code completed Mocking and Stubbing for Swift protocols and classes.","archived":false,"fork":false,"pushed_at":"2020-11-03T15:49:07.000Z","size":698,"stargazers_count":3,"open_issues_count":4,"forks_count":1,"subscribers_count":3,"default_branch":"develop","last_synced_at":"2025-04-09T23:54:18.866Z","etag":null,"topics":["mock","mocking","stub","stubbing","swift","swift4"],"latest_commit_sha":null,"homepage":null,"language":"Swift","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/CuratoOpenSource.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":"2018-05-21T21:41:20.000Z","updated_at":"2023-03-10T10:26:13.000Z","dependencies_parsed_at":"2022-11-01T23:05:49.272Z","dependency_job_id":null,"html_url":"https://github.com/CuratoOpenSource/Mock-N-stub","commit_stats":null,"previous_names":["mennolovink/mock-n-stub"],"tags_count":24,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CuratoOpenSource%2FMock-N-stub","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CuratoOpenSource%2FMock-N-stub/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CuratoOpenSource%2FMock-N-stub/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CuratoOpenSource%2FMock-N-stub/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/CuratoOpenSource","download_url":"https://codeload.github.com/CuratoOpenSource/Mock-N-stub/tar.gz/refs/heads/develop","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248131452,"owners_count":21052819,"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","stub","stubbing","swift","swift4"],"created_at":"2024-09-24T20:40:17.651Z","updated_at":"2025-04-09T23:54:22.252Z","avatar_url":"https://github.com/CuratoOpenSource.png","language":"Swift","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Mock 'N Stub\n\n![GitHub release (latest by date)](https://img.shields.io/github/v/release/lvnkmn/mock-n-stub) [![Platform](http://img.shields.io/cocoapods/p/MockNStub.svg?style=flat)](http://cocoapods.org/pods/Zoomy) [![License](http://img.shields.io/cocoapods/l/MockNStub.svg?style=flat)](LICENSE)\n\nCode completed Mocking and Stubbing for Swift protocols and classes.\n\n## Setup\n\nJust add:\n\n```Swift\nimport MockNStub\n```\n\nto the files where you need to create mocks or stubs.\n\n## All Mocks are Stubs\n\nAll created mocks conform to the `Mocking` protocol and since `Mocking` conforms to the `Stubbing` protocol, all created mocks can automatically be used as stubs too.\n\nWenever you feel that an explicit stub needs to support `Mocking`, all you need to do is change it's conformance from `Stubbing` to `Mocking`. \n\n## Class and Protocol Mocks/Stubs share the exact same interface\nThe implementations in MockNStub are completely protocol oriented. This allows the interface of class and protocol mocks (and stubs) to be exactly the same. All explicit stubs conform to `Stubbing` and all mocks conform to `Mocking`. There's never a need to inherit from a concrete type from this library.\n\n## Stubbing\n### Creating stubs\n#### Using function names\n```Swift\nclass UITableViewDataSourceStub: Stubbing, UITableViewDataSource {\n\n    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -\u003e Int {\n        return didCallFunction(withArguments: tableView, section)\n    }\n    \n    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -\u003e UITableViewCell {\n        return didCallFunction(withArguments: tableView, indexPath)\n    }\n}\n```\nNotes:\n\n* No need to manually provide a function name.\n\n### Adding return values to stubs\nReturn values can be added as many times as desired, in the case where they are provided for the same signature, the value that was last provided is returned.\n\n#### Using function names\nConsidering:\n\n```Swift\nlet stub = UITableViewDataSourceStub()\n```\n\nYou can add stub values like this:\n\n```Swift\nstub.given(\"tableView(_:numberOfRowsInSection:)\", willReturn: 0)\nstub.given(\"tableView(_:cellForRowAt:)\", willReturn: UITableViewCell())\n```\n\nOr when needing to be more specific, like this:\n\n```Swift\nstub.given(\"tableView(_:numberOfRowsInSection:)\"), withArgumentsThatMatch: ArgumentMatcher(matcher: { (args: (UITableView, Int)) -\u003e Bool in\n\treturn args.0 === expectedTableView \u0026\u0026 args.1 == 2\n}), willReturn: 42)\n```\nNotes:\n\n* Argument matcher won't match if argument types are not correct.\n\n## Mocking\n### Creating mocks\n#### Using function names\n\n```Swift\nclass UITableViewDataSourceMock: NSObject, Mocking, UITableViewDataSource {\n    \n    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -\u003e Int {\n        return didCallFunction(withArguments: tableView, section)\n    }\n    \n    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -\u003e UITableViewCell {\n        return didCallFunction(withArguments: tableView, indexPath)\n    }\n}\n```\n\n### Creating expectations\n#### Using function names\n\n```Swift\nlet mock = UITableViewDataSourceMock()\n```\n\nYou can add expectations like this:\n\n```Swift\nmock.expect(callToFunction: \"tableView(_:cellForRowAt:)\")\nmock.expect(callToFunction: \"tableView(_:numberOfRowsInSection:)\")\n```\n\nOr when needing to be more specific, like this:\n\n```Swift\nmock.expect(callToFunction: \"tableView(_:numberOfRowsInSection:)\", withArgumentsThatMatch: ArgumentMatcher(matcher: { (args: (UITableView, Int)) -\u003e Bool in\n\treturn args.0 === tableView \u0026\u0026 args.1 == 42                        \n}))\n```\n\nIt's also possible to expect an exact amount of calls:\n\n```Swift\nmock.expect(.exactly(amount: 42), callsToFunction: \"tableView(_:cellForRowAt:)\")\n```\n\nor \n\n```Swift\nmock.expect(.exactly(amount: 42), callsToFunction: \"tableView(_:numberOfRowsInSection:)\", withArgumentsThatMatch: ArgumentMatcher(matcher: { (args: (UITableView, Int)) -\u003e Bool in\n\treturn args.0 === tableView \u0026\u0026 args.1 == 42                        \n}))\n```\n\n\n### Verifying\n\nregardless of how methods have been identified:\n\n```Swift\nmock.verify()\n```\n\nNotes:\n\n* This will result in an XCT failure when one ore more expectations have not been met.\n\n### Properties\n\nMocking and stubbing properties is done like expected.\n\n#### Using function names\n\n```Swift\nvar title: String {\n    get {\n        return didCallFunction()\n    }\n    set {\n        didCallFunction(withArguments: newValue)\n    }\n}\n```\n\nNotes:\n\n* This get set pattern is identical on any property.\n\n### Default return values of didCall()\nWithin the `Mocking` and `Stubbing` protocols there's a quite a bunch of implementations for the `didCall` methods. Because of Swifts support for type inference, the correct method will be used at compile time. For instance when `return didCallFunction()` a non void implementation of `didCallFunction()` will be used. Even more exciting, when `return didCallFunction()` is called in a method that returns a value that conforms to `ProvidingDefaultStubValue` there will be no need to unwrap the result of `didCallFunction` because the default value is known (and provided) through the default protocol implementation. Note: these default stub values will only be provided when no other values are provided through the `given...` methods.\n\nDon't worry too much about what is explained above, long story short: your IDE will always give you the most sensible option that's available.\n\nIn the case where a type that does not conform to `ProvidingDefaultStubValue` needs to be returned. The compiler won't sugest (and allow) a version of `didCall..` that returns a nonoptional value. You can do three things in this case:\n\n* Make that type conform to `ProvidingDefaultStubValue`\n\t* If you do this for a type from one of Apple's libraries, a pull request to this repo containing this extension would be highly appreciated. \n* Manually provide a default value in case nil is provided: `return didCallFunction() ?? MyType()`\n* Force unwrap the return value provided by the `didCall`\n\t* In this case you do want to make sure a value is present using the `given..` methods.\n\t\t* When this isn't done, your test will crash when calling the stubbed or mocked method.\n\t\t* However, every force unwrap of a nil value is known before it occurs and will cause detailed diagnosics to be logged to the console which shows what was expected to happen vs. what actually happened:![Screenshot Missing](Art/LogWhenForceUnwappingReturnValue.png)\n\n#### Types that currently conform to `ProvidingDefaultStubValue`\n* Most types from the Swift Standard library\n* Most commonly used types from UIKit\n* Most commonly used types CoreGraphics\n* All types that inherit from NSObject\n\t* Dislaimer; these subclasses do need to adhere to the [Liskov Substitution Principle](https://en.wikipedia.org/wiki/Liskov_substitution_principle) or in simpler terms: don't have a `fatalError()` or anything similar in their `init()`\n\n[Here's](https://github.com/mennolovink/Mock-N-stub/tree/develop/MockNStub/Classes/Extensions/ProvidingDefaultStubValue) an overview of all types that currently conform to `ProvidingDefaultStubValue `\n\n## Defining function ID's\n\nA way of reducing errors caused by typo's is by having your Mocks and Stubs conform to `DefiningFunctionID`\n\nConforming to `DefiningFunctionID` is done as follows:\n\n\textension UITableViewStub : DefiningFunctionID {\n\t    typealias FunctionID = FuncID\n\t    \n\t    enum FuncID: String {\n\t        case numberOfRows\n\t        case cellForRowAt\n\t    }\n\t}\n\n_Note: the example above is done for a stub but is done just the same for mocks_\n\nConforming to `DefiningFunctionID` will unlock the following range of mock and stub methods:\n\n    didCallFunction(withID: .numberOfRows)\n    mock.expect(callToFunctionWithID: .numberOfRows)\n\n## There's more to come..\n\n### Planned features\n\nCan be viewed in the [roadmap](https://github.com/mennolovink/Mock-N-stub/issues?q=is%3Aissue+is%3Aopen+label%3Aroadmap).\n\n### Anything missing?\n\nCreate a [feature request](https://github.com/mennolovink/Mock-N-stub/issues/new) and it will likely be picked up.\n\n## Installation\n\nMockNStub is available through [Swift Package Manager](https://swift.org/package-manager/). To install it, simply add it to your project using this repository's URL as explained [here](https://developer.apple.com/documentation/xcode/adding_package_dependencies_to_your_app).\n\n## License\n\nMockNStub is available under the MIT license. See the LICENSE file for more info.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcuratoopensource%2Fmock-n-stub","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcuratoopensource%2Fmock-n-stub","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcuratoopensource%2Fmock-n-stub/lists"}