{"id":13466133,"url":"https://github.com/leoture/MockSwift","last_synced_at":"2025-03-25T21:31:17.677Z","repository":{"id":35697263,"uuid":"200196202","full_name":"leoture/MockSwift","owner":"leoture","description":"MockSwift is a Mock library written in Swift.","archived":false,"fork":false,"pushed_at":"2022-08-30T17:33:07.000Z","size":1937,"stargazers_count":90,"open_issues_count":0,"forks_count":7,"subscribers_count":8,"default_branch":"master","last_synced_at":"2024-10-29T19:16:31.909Z","etag":null,"topics":["mock","playground","swift","swift-package-manager","test","xcode"],"latest_commit_sha":null,"homepage":"https://adoring-varahamihira-bbe99d.netlify.app/documentation/","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/leoture.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-08-02T08:24:09.000Z","updated_at":"2024-10-12T19:36:32.000Z","dependencies_parsed_at":"2022-08-08T10:17:06.689Z","dependency_job_id":null,"html_url":"https://github.com/leoture/MockSwift","commit_stats":null,"previous_names":[],"tags_count":9,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/leoture%2FMockSwift","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/leoture%2FMockSwift/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/leoture%2FMockSwift/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/leoture%2FMockSwift/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/leoture","download_url":"https://codeload.github.com/leoture/MockSwift/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245547284,"owners_count":20633338,"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","playground","swift","swift-package-manager","test","xcode"],"created_at":"2024-07-31T15:00:39.620Z","updated_at":"2025-03-25T21:31:17.198Z","avatar_url":"https://github.com/leoture.png","language":"Swift","funding_links":[],"categories":["Libs","Testing [🔝](#readme)"],"sub_categories":["Testing"],"readme":"\u003cp align=\"center\"\u003e\n  \u003cimg src=\"https://raw.githubusercontent.com/leoture/MockSwift/master/MockSwift.svg?sanitize=true\" alt=\"MockSwift\" width=\"256\"\u003e  \n\u003c/p\u003e\n\nWelcome to MockSwift\n=======\n\n[![Release](https://img.shields.io/github/v/release/leoture/MockSwift?color=red)](https://github.com/leoture/MockSwift/releases)\n[![Build Status](https://github.com/leoture/MockSwift/workflows/Master/badge.svg?branch=master)](https://github.com/leoture/MockSwift/actions)\n[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=leoture_MockSwift\u0026metric=alert_status)](https://sonarcloud.io/summary/new_code?id=leoture_MockSwift)\n[![Netlify Status](https://api.netlify.com/api/v1/badges/08a89377-0a44-4f0e-a17c-9ee7d18e07bd/deploy-status)](https://app.netlify.com/sites/adoring-varahamihira-bbe99d/deploys)\n[![Swift Package Manager compatible](https://img.shields.io/badge/Swift%20Package%20Manager-Compatible-brightgreen)](https://github.com/apple/swift-package-manager)\n[![Swift](https://img.shields.io/badge/Swift-5.5-important)](https://swift.org)\n[![license MIT](https://img.shields.io/badge/license-MIT-informational)](https://github.com/leoture/MockSwift/blob/master/LICENSE)  \n\n**MockSwift** allows you to [**write mocks**](#write-mocks) and [**make better tests**](#make-better-tests). Because **MockSwift** is an **open source** library **100%** written in **Swift**, it is **AVAILABLE ON ALL PLATFORMS**.  \nInitially MockSwift is inspired by [Mockito](https://site.mockito.org).  \n\n###### Table of Contents\n\n- [Installation](#installation)\n- [Usage](#usage)\n- [Documentation](#documentation)\n- [Contribution](#contribution)\n- [License](#license)\n\n# Installation\n## Swift Package Manager\nMockSwift has been designed to work with [Swift Package Manager](https://swift.org/package-manager/).\n```swift\n// swift-tools-version:5.3\n\nimport PackageDescription\n\nlet package = Package(\n  name: \"MyProject\",\n  dependencies: [\n    .package(url: \"https://github.com/leoture/MockSwift.git\", from: \"1.0.0\")\n  ],\n  targets: [\n    .testTarget(name: \"MyProjectTests\", dependencies: [\"MockSwift\"])\n  ]\n)\n```\n\n# Usage\n## Quick Look\n```swift\nclass AwesomeTests: XCTestCase {\n\n  private var printer: Printer!\n  @Mock private var userService: UserService\n\n  override func setUp() {\n    printer = Printer(userService)\n  }\n\n  func test_sayHello() {\n    // Given\n    given(userService).fetchUserName(of: \"you\").willReturn(\"my friend\")\n    given(userService).isConnected.get.willReturn(true)\n    given(userService)[cache: .any()].set(.any()).willDoNothing()\n\n    // When\n    let message = printer.sayHello(to: \"you\", from: \"me\")\n\n    // Then\n    then(userService).fetchUserName(of: .any()).called()\n    then(userService).isConnected.get.called(times: 1)\n    then(userService)[cache: \"you\"].set(\"my friend\").calledOnce()\n    \n    XCTAssertEqual(message, \"me: Hello my friend\")\n  }\n}\n```\n\n## Details\nSuppose that you have a `UserService` protocol.\n```swift\nstruct User: Equatable {\n  let identifier: String\n  let name: String\n}\n\nprotocol UserService {\n  func fetch(identifier: String) -\u003e User\n}\n```\n\nAnd you want to test this `UserCore` class.\n```swift\nclass UserCore {\n  private let service: UserService\n\n  init(_ service: UserService) {\n    self.service = service\n  }\n\n  func fetchCurrentUser() -\u003e User {\n    service.fetch(identifier: \"current\")\n  }\n}\n```\n\n## Make better tests\n\nNow, with MockSwift, you can use a mocked `UserService` in your tests with the `@Mock` annotation.\n\n```swift\n@Mock private var service: UserService\n\n// equivalent to\n\nprivate var service: UserService = Mock()\n```\n\nAnd easly configure it to fully test `UseCore`.\n\n```swift\nclass UserCoreTests: XCTestCase {\n\n  private var core: UserCore!\n  @Mock private var service: UserService\n\n  override func setUp() {\n    core = UserCore(service)\n  }\n\n  func test_fetchCurrentUser() {\n    // Given\n    let expectedUser = User(identifier: \"current\", name: \"John\")\n\n    given(service).fetch(identifier: .any()).willReturn(expectedUser)\n\n    // When\n    let user = core.fetchCurrentUser()\n\n    // Then\n    then(service).fetch(identifier: .any()).called()\n    XCTAssertEqual(user, expectedUser)\n  }\n}\n```\n\n### Given\n`given()` enables you to define behaviours.  \nexample:\n```swift\ngiven(service).fetch(identifier: .any()).willReturn(expectedUser)\n\n// equivalent to\n\ngiven(service) {\n  $0.fetch(identifier: .any()).willReturn(expectedUser)\n}\n```\n\n```swift\ngiven(service) {\n  $0.fetch(identifier: \"current\")\n    .willReturn(expectedUser, expectedUser1, expectedUser2)\n\n  $0.fetch(identifier: .match(when: \\.isEmpty))\n    .will { (params) -\u003e User in\n            // do something else\n            return expectedUser\n          }\n}\n```\n\nyou can also define behaviours when you instantiate the mock.\n\n```swift\n@Mock({\n  $0.fetch(identifier: .any()).willReturn(expectedUser)\n})\nprivate var service: UserService\n```\n\n### Then\n`then()` enables you to verify calls.  \nexample:\n\n```swift\nthen(service).fetch(identifier: .any()).called()\n\n// equivalent to\n\nthen(service) {\n  $0.fetch(identifier: .any()).called()\n}\n```\n\n```swift\nthen(service) {\n  $0.fetch(identifier: \"current\").called(times: \u003e=2)\n\n  $0.fetch(identifier: == \"\").called(times: 0)\n}\n```\n\nYou can go further and verify order of calls\n```swift\nlet assertion = then(service).fetch(identifier: \"current\").called(times: \u003e=2)\nthen(service).fetch(identifier: == \"\").called(times: 1, after: assertion)\n```\n\n### Stubs\n\nIn MockSwift, stubs are default values that are returned when no behaviours has been found.\n\n#### Global Stubs\n\nYou can define a **global stub** for any type.\nIt will concern **all mocks** you will use in **every tests**.\n\n```swift\nextension User: GlobalStub {\n  static func stub() -\u003e User {\n    User(identifier: \"id\", name: \"John\")\n  }\n}\n```\n\n#### Local Stubs\nYou can also define a **stub localy** for any type.\nIt will concern only the **current mock**.\n```swift\n@Mock(localStubs: [\n      User.self =\u003e User(identifier: \"id\", name: \"John\")\n])\nprivate var service: UserService\n```\n\n### Strategy\nThe default strategy is to find behaviour defined with `given()`. If no behaviour is found, it will return a local stub. If no local stub is found, it will return a global stub.\n\n```swift\n@Mock private var service: UserService\n\n// equivalent to\n\n@Mock(strategy: .default)\nprivate var service: UserService\n\n// equivalent to\n\n@Mock(strategy: [.given, .localStubs, .globalStubs])\nprivate var service: UserService\n```\n\nYou can change the order of the strategy list or remove items as you want.\n\n## Write mocks\n### Automatically\nMockSwift provides a [stencil template](https://github.com/leoture/MockSwift/blob/master/Templates/MockSwift.stencil) for [sourcery](https://github.com/krzysztofzablocki/Sourcery). You can use the `AutoMockable` annotation to generate code.\n```swift\n// sourcery: AutoMockable\nprotocol UserService {\n  func fetch(identifier: String) -\u003e User\n}\n```\n\nTo generate code at every build, you can add a build phase before `Compile Sources`.\n```\nsourcery \\\n--sources MyLibrary \\\n--templates MyLibraryTests/path/to/MockSwift.stencil \\\n--output MyLibraryTests/path/to/GeneratedMocks.swift \\\n--args module=MyLibrary\n```\n\n### Manually\nTo enable MockSwift for UserService type, you have to extend **Mock**.\n```swift\nextension Mock: UserService where WrappedType == UserService {\n  public func fetch(identifier: String) -\u003e User {\n    mocked(identifier)\n  }\n}\n```\n\nTo allow behaviour definition through `given()` method, you have to extend **Given**.\n```swift\nextension Given where WrappedType == UserService {\n  public func fetch(identifier: Predicate\u003cString\u003e) -\u003e Mockable\u003cUser\u003e {\n    mockable(identifier)\n  }\n  public func fetch(identifier: String) -\u003e Mockable\u003cUser\u003e {\n    mockable(identifier)\n  }\n}\n```\n\nTo allow call verification through `then()` method, you have to extend **Then**.\n```swift\nextension Then where WrappedType == UserService {\n  public func fetch(identifier: Predicate\u003cString\u003e) -\u003e Verifiable\u003cUser\u003e {\n    verifiable(identifier)\n  }\n  public func fetch(identifier: String) -\u003e Verifiable\u003cUser\u003e {\n    verifiable(identifier)\n  }\n}\n```\n\n# Documentation\nIf you need more details about the API, you can check out our [API documentation](https://adoring-varahamihira-bbe99d.netlify.app).\n\n# Contribution\nWould you like to contribute to MockSwift? Please read our [contributing guidelines](https://github.com/leoture/MockSwift/blob/master/CONTRIBUTING.md) and [code of conduct](https://github.com/leoture/MockSwift/blob/master/CODE_OF_CONDUCT.md).\n\n# License\nMockSwift is released under the MIT license. [See LICENSE](https://github.com/leoture/MockSwift/blob/master/LICENSE) for details.\n\n# Credits\n[![Thanks to JetBrains](https://raw.githubusercontent.com/leoture/MockSwift/master/jetbrains.svg?sanitize=true)](https://www.jetbrains.com/?from=MockSwift)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fleoture%2FMockSwift","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fleoture%2FMockSwift","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fleoture%2FMockSwift/lists"}