SwiftyMocky Documentation

repository·master·Indexed 22 days ago

https://github.com/makeawishfoundation/swiftymocky

A strongly typed mocking framework for Swift that uses Sourcery to automatically generate mock implementations of protocols. It provides a Mockito-like testing experience with features including support for generics, return value stubbing via `Given`, invocation verification via `Verify`, and custom action execution via `Perform`. The framework includes a CLI for mock generation and supports integration via CocoaPods, Carthage, and Swift Package Manager.

Tokens
18.6K
Snippets
68
Records
91
Agent score
77%

What's inside SwiftyMocky

  1. Overview of SwiftyMocky

    master

    SwiftyMocky is a strongly typed framework designed for a Mockito-like unit testing experience in Swift. It leverages Sourcery to scan your source code and automatically generate Swift mock implementations for protocols and protocol compositions.

    Key features include:

    • Support for generics.
    • Easy syntax utilizing IDE auto-complete.
    • Ability to specify return values via given.
    • Support for recording sequences of return values.
    • Verification of method invocations and attributes via verify.
    • Ability to perform actions when stubbed methods are called via perform.
    • Compatibility with real devices.
  2. Mock Generation capabilities in SwiftyMocky

    master

    SwiftyMocky supports several ways to generate mocks for your Swift protocols:

    • Inline mocks: Generating mocks directly within your test files.
    • AutoMockable protocol: Generating mocks in Mocked.generated based on the AutoMockable protocol.
    • AutoMockable annotation: Generating mocks in Mocked.generated based on the AutoMockable annotation.

    Supported Type Handling:

    • Protocol inheritance.
    • Objective-C protocols (requires special protocol/annotation).
    • Generic protocols.
    • Associated types (handled via annotations).
    • Conformances in associated types.
  3. Verify method calls using Verify

    master

    The Verify syntax is used to assert that a specific stubbed method was called on a Mock with specific arguments.

    Argument Constraints: Use .any or .value(ValueType) (subject to Equatable and Matcher rules) to specify which calls should be verified.

    Verification Capabilities:

    • Verify if a method was called at least once.
    • Verify if a method was called exactly a specific number of times.
    • Verify calls for static methods.
  4. Specify stub behavior using Given

    master

    The Given syntax is used to specify return values or errors thrown when a stubbed method is called. You can constrain arguments using:

    • .any: Matches any value.
    • .value(ValueType): Matches an explicit value. This works for:
      • Equatable types.
      • Sequences of Equatable elements.
      • Non-Equatable types (if a comparator is registered in the Matcher).
      • @escaping closures that are Equatable (if a comparator is registered in the Matcher).

    Note: If a ValueType is not an @escaping closure, it is always handled as .any if it doesn't meet the criteria above.

    Supported Scopes:

    • Return values and errors for instance stubs.
    • Return values and errors for static stubs.
  5. Mark protocols to be mocked

    master

    To tell SwiftyMocky which protocols should have mocks generated, you must mark them using one of the following methods. All marked protocols will be added to Mock.generated.swift.

    Method 1: Adopt AutoMockable

    Create a dummy protocol and have your target protocols inherit from it:

    protocol AutoMockable { }
    
    protocol ToBeMocked: AutoMockable { 
      // ...
    }

    Method 2: Sourcery Annotation

    Add a //sourcery: AutoMockable comment above the protocol definition:

    //sourcery: AutoMockable
    protocol ToBeMocked { 
      // ...
    }

    Method 3: Protocol Composition

    Apply AutoMockable to a typealias of composed protocols:

    typealias ToBeMocked = OneProtocol & TwoProtocols & AutoMockable
    //sourcery: AutoMockable
    protocol ToBeMocked {
      // ...
    }
  6. Mark protocols for mocking using AutoMockable protocol

    master

    You can mark protocols to be included in Mock.generated.swift by having them inherit directly from a dummy AutoMockable protocol.

    Define the protocol in your project as follows:

    protocol AutoMockable { }
    
    // Any protocol inheriting directly from AutoMockable will be mocked
    protocol ToBeMocked: AutoMockable {
      // ...
    }
  7. Mark protocols for mocking using AutoMockable annotation

    master

    You can use Sourcery annotations to mark protocols for mocking without changing their inheritance hierarchy.

    For standard Swift protocols, use //sourcery: AutoMockable.

    For @objc protocols, you must provide both the AutoMockable and ObjcProtocol annotations:

    // Standard Swift protocol
    //sourcery: AutoMockable
    protocol ToBeMocked {
      // ...
    }
    
    // @objc protocol
    //sourcery: AutoMockable
    //sourcery: ObjcProtocol
    @objc protocol NonSwiftProtocol {
      // ...
    }
  8. Use SwiftyPrototype for in-app prototyping

    master

    While SwiftyMocky is designed for testing, you can use SwiftyPrototype to fake or prototype behavior directly inside your application (running on a device).

    SwiftyPrototype is a separate library extracted from SwiftyMocky that does not rely on the XCTest framework, making it suitable for production/runtime use.

    To use it:

    1. Install the SwiftyPrototype runtime via CocoaPods, Carthage, or Swift Package Manager.
    2. Install the SwiftyMocky CLI for mock generation.
    3. In your Mockfile, mark the specific target you want to prototype with prototype: true.
  9. Stubbing protocol members with SwiftyMocky

    master

    SwiftyMocky allows you to stub various members of a protocol to control their behavior during tests:

    • Initializers: Supported only for protocol conformance (they have empty implementations).
    • Instance Methods: Can be stubbed to return a value, throw an error, or rethrow an error.
    • Static Methods: Supported.
    • Generic Methods: Supports constraints to protocol conformance, T.Type attributes, and constraints to the Self type.
    • Variables: Supports both instance and static variables, including optional and implicitly unwrapped optional types.
    • Subscripts: Supported (note: generic subscripts require manual annotation).
    • Method Attributes: Supports wrapping attributes as Parameter, including basic types, closures, @escaping closures, and typealiases.
  10. Execute side effects using Perform

    master

    The Perform syntax allows you to execute a closure when a stubbed method is called. This is useful for capturing arguments or triggering side effects.

    Argument Constraints: Similar to Given, you can constrain the arguments of the Perform closure using .any or .value(ValueType) (with the same rules for Equatable and Matcher registration).

    Supported Scopes:

    • Perform closures for instance methods.
    • Perform closures for static methods.
  11. Understand the Mockfile format

    master

    A Mockfile is a YAML configuration used by SwiftyMocky to define which sources should be mocked, where the generated files should be placed, and which modules should be imported. You can define multiple configurations within a single file, where each configuration represents one generated mock file. This allows you to manage separate mocks for different test targets.

    Key configuration sections include:

    • sources: Defines the include and exclude paths (relative to project root) for scanning AutoMockable types.
    • output: The file path and name for the generated mocks. Defaults to Mock.generated.swift if only a path is provided.
    • targets: A list of test target names that use the generated mocks. This is used for linting and validation.
    • testable: A list of modules to be @testable imported at the top of the generated file.
    • import: A list of modules to be imported at the top of the generated file.
    • sourcery: Optional paths to additional Sourcery configurations to run alongside mock generation.
    mock_config_name:
        sources:
            include:
            - ./MyApp
            exclude: []
        output:
            ./MyAppUnitTests/Mocks/Mock.generated.swift
        targets:
            - MyAppUnitTests
        testable: [MyApp]
        import: [Foundation]
        prototype: false