Mimic

Mimic: Mock Generator for Xcode

πŸ‘ 2.0 Update coming soon

A major update is coming before migrating Mimic to use Swift Macros. ETA is December 18th 2023

Mimic is an Xcode editor extension that lets you generate the boilerplate code for mocks. you can genrate Spy, Partial Spy, Stubs, and Dummy mocks with the click of a button (or keyboard shortcut).

The companion application can be used to easily grant permissions to your projects and configure various rendering options.

All generated code is native swift and has no custom DSL, which offers you the flexibility to deliver and utilise the generated output within your own architectures and testing setups.

1.0.4 Currently available for purchase on the app store!

app-store-badge-1.png

Recent Version History

2.0.0: In development:

Note: 2.0.0 will also adopt MimicKit - the library that handles source code resolving, parsing, and mock generation. This library will also be open-sourced 😎

  • [BUG] Support for inout properties
  • [BUG] Better support for protocols with inheritence
  • [BUG] Support for protocols with primary associated types
  • [BUG] Better support for functions and variables named the same across different protocols
  • [FEATURE] Default values generated for tuples and closures
  • [STRETCH] Generate test doubles inheriting from types within SPM dependencies
  • [STRETCH] Support for throwing closures
  • [STRETCH] Support for operator declarations
  • [STRETCH] Better support for classes/subclasses with complex generics

1.0.4: Current AppStore Version:

  • [BUG] Fixed issue where some function partial spies were not generating super calls
  • [BUG] Fixed issue where sidebar unable to be re-opened
  • [UPDATE] Unable to resolve Package-based directory permissions 😞

1.0.3

  • [BUG] Ensure correct indentation/formatting when generating for nested type
  • [BUG] Don't re-generate initializers that having matching signatures across multiple inheritances πŸ˜…
  • [BUG] Fix random ordering of generated functions
  • [BUG]/[Feature] Better feedback for stale or corrupt project permissions
  • [BUG] Fix bug where Package.swift files in root directory cause permission errors

1.0.2

  • [BUG] Exclude optional symbol from stubbed subscript properties
  • [BUG] Default subscript generics with no type requirement to Any when expanding
  • [BUG] Honour optional outputs in subscripts
  • [BUG] Enforce standardised init order

1.0.1

  • Added support for Swift Playground project types
  • Fixed bug where duplicate keywords would appear on some initializers
  • Ensured redundant convenience init is not included in output when not required
  • Fixed bug parsing some attributes in function parameters

1.0.0

Initial release. See Features for inclusions

Features

GENERAL:


  • βœ… Swift 5.0+
  • βœ… Generate Spy
  • βœ… Generate Stub
  • βœ… Generate Dummy
  • βœ… Generate Partial Spy
  • βœ… Xcode 11+

CURRENTLY IN DEVELOPMENT:


  • πŸ›  Conslidating duplicate properties/functions from multiple inheritence types (it happens)
  • πŸ›  Default values for closures and tuples etc

IN THE BACKLOG:


  • πŸ›  Generate test doubles inheriting from SPM dependencies
  • πŸ›  Support for throwing closures
  • πŸ›  Better support for classes/subclasses with complex generics
  • πŸ›  Better support for valid attributes (@available, #if , etc)
  • πŸ›  Support for operator declarations
  • πŸ›  More stable support for UI attributes such as IBOutlets and IBActions etc
  • πŸ›  Workaround for static/class properties not supported with Generics

SETTINGS:


  • βœ… Support resolving and expanding raw TypeAlias definitions
  • βœ… Support assigning default values where possible (defaults to code tag)
  • βœ… Support assigning nil for default value for optionals
  • βœ… Support rendering code tags when a default value can't be assigned
  • βœ… Support including unique methods/properties declared on type extensions
  • βœ… Feedback for stale or corrupt permissions

CONFORMANCE AND INHERITANCE:


  • βœ… Generates TypeAlias for Associated Types
  • βœ… Generates for multiple inheritance/conformance
  • βœ… Generates for mix of class and protocol conformance
  • βœ… Generate test doubles inheriting from carthage dependencies
  • βœ… Generate test doubles inheriting from cocoapods dependencies

RECORDING AND INVOCATIONS:


  • βœ… Captures invocation status + count for getters, setters, and methods
  • βœ… Captures invocation status + count for subscripts
  • βœ… Captures invocation input parameters for methods
  • βœ… Captures invocation input parameters for subscripts
  • βœ… Captures multiplate invocation input parameters for methods
  • βœ… Captures multiplate invocation input parameters for subscripts

GENERICS


  • βœ… Supports classes with generics
  • βœ… Supports methods and variables with generics
  • βœ… Supports generic inputs/parameters
  • βœ… Supports generic inputs/parameters in closures
  • βœ… Supports generic return results

CLOSURES:


  • βœ… Supports escaping/auto-escaping closure parameters
  • βœ… Generates invocation and inputs for closure parameters
  • βœ… Automatically calls closure parameters with stubbed values

STUBBED RESULTS:


  • βœ… Stubs values for your test doubles to return
  • βœ… Stubs a default value for return values where possible
  • βœ… Stubs return values for within generated closures

SCOPES AND KEYWORDS:


  • βœ… Will avoid naming clashes in generated output per inheritence
  • βœ… Supports type-annotation for annotations and attributes

VISIBILITY FLAGS:


  • βœ… Respects public/open visibility flags
  • βœ… Ignores final, private, and static methods (unable to override)

INITIALIZERS:


  • βœ… Generates convenience initializer with default values where possible
  • βœ… Supports initializers with arguments
  • βœ… Supports throwable initializers
  • βœ… Supports required initializers
  • βœ… Supports super calls in initializers

THROWS:


  • βœ… Generates error stub for throwing methods
  • βœ… Generates error stub for throwing initializer (when possible)

Installation and Usage

πŸ› οΈ You should quit Xcode before doing these steps as the extension won't appear if Xcode is running. You can also restart Xcode once granting access.

You will need to grant permissions for the extension to work. This is fairly simple however.

1: Enable the extension in System Preferences:

After launching the application you first need to grant permissions for the extension in your System Preferences app. Launch the preferences and click the Extensions option. Click Xcode Source Editor and check the Mimic checkbox:

setup.png

2: Add the project/s you want to use the extension for:

Launch the Mimic app and use the Projects menu item to add permissions for your projects. Currently standard xcodeproj and xcworkspace projects are permitted for selection.

adding.png

3: Grant access when first using the extension:

The first time you use the extension you will see a dialogue box requesting permission for Mimic to control Xcode. The language is odd considering the function, but you will need to grant this access in order for Xcode to resolve the active project path and put any generated code in your current editor:

xcode-permissions.png

4: Generating a mock in Xcode:

Once you have setup permissions to your project the extension can generate mock templates for you.

For example lets say you had MyAwesomeProtocol and wanted to generate a Spy for it:

typealias Person = (name: String, age: Int)

protocol MyAwesomeProtocol {

    var readOnlyTitle: String { get }

    var mutableMessage: String { get set }

    var person: Person { get set }

    func updatePerson(_ person: Person)

    init(title: String, message: String)

    init(title: String) throws
}
Declare your mock class and inheritance:

Write your declaration class and conform to the desired protocol (or multiple protocols and class etc) - then select anywhere inside it:

dec.png

then select the Editor > Mimic menu item and choose the template you want to render:

select-mimic.png

the extension will do it's thing and then populate your mock class with the output:

output-final.png

Troubleshooting:


My testers (and myself) have done our best to test against all sorts of... unique code examples when using the Mimic generator, however, if something is not rendering correctly or things are going wrong we have found a few common scenarios you can look at before reaching out to support:

Output is empty:

If the generator command is outputting an empty string in your mock class then we have found this is usually because the project directory exists but permissions are stale. If the companion app has not detected this, or you have not checked in a while, we would suggest launching the Mimic app and removing/re-adding permissions to the project directory.

Note: I am currently working on better detection for these scenarios to keep you alerted of when permissions need to be re-added.

Formatting is weird:

If your generated output is formatted extremely odd (usually weird indentations) this is usally due to existing code within the target mock class (or in the type being mocked) being uncompilable or invalid swift syntax. We would suggest checking the project is compilable before trying again, or removing all code within the mock class and trying again.

My code is super unique:

As noted before, we experimented with heaps of scenarios that we would hope you don't have to deal with. However, depending on the code quality of the project you inherited, there may be some things Mimic does not completely support. In these cases please submit a bug or feature request with an example of the declaration and the current output being generated. I can't fix or add something if I don't know about it πŸ˜…

Feature Requests/Bug Reports


If you find a bug, or find something you want support added for, please submit a bug or feature request

I cant fix something or add things you want if I don't know about them, I actively maintain Mimic every week. I prioritize bugs and am always up for adding popular feature requests as they come in.

You can see the current features in development in the Feature Table section above.

Privacy Policy:


Privacy Policy

Cheeky Ghost Labs built the Mimic app as a Commercial app. This SERVICE is provided by Cheeky Ghost Labs and is intended for use as is.

This page is used to inform visitors regarding my policies with the collection, use, and disclosure of Personal Information if anyone decided to use my Service.

If you choose to use my Service, then you agree to the collection and use of information in relation to this policy. No Personal Information is knowingly requested or collected. Any information that I collect is used for providing and improving the Service. I will not use or share this information with anyone except as described in this Privacy Policy.

The terms used in this Privacy Policy have the same meanings as in our Terms and Conditions, which are accessible at Mimic unless otherwise defined in this Privacy Policy.

Information Collection and Use

For a better experience, while using our Service, I log basic information, including but not limited to error and basic usage logs. The information that I request is end to end encrypted.

Log Data

I want to inform you that whenever you use my Service, in a case of an error in the app I collect data and information (through third-party products) on your mac called Log Data. This Log Data may include information such as your device Internet Protocol (β€œIP”) address, device name, operating system version, the configuration of the app when utilizing my Service, the time and date of your use of the Service, and other statistics. No personal information is logged.

Service Providers

I may employ third-party companies and individuals due to the following reasons:

To facilitate logging errors while using our Service; To assist us in analyzing how our Service is used. I want to inform users of this Service that these third parties have access to their Personal Information. The reason is to perform the tasks assigned to them on our behalf. However, they are obligated not to disclose or use the information for any other purpose.

Security

I value your trust and while no personal identifiable information is collected or requested while using this service. Remember that no method of transmission over the internet, or method of electronic storage is 100% secure and reliable, and I cannot guarantee its absolute security.

Children’s Privacy

I do not knowingly collect personally identifiable information from children (or any users). I encourage all children to never submit any personally identifiable information through the Application and/or Services. I encourage parents and legal guardians to monitor their children's Internet usage and to help enforce this Policy by instructing their children never to provide personally identifiable information through the Application and/or Services without their permission. If you have reason to believe that a child has provided personally identifiable information to us through the Application and/or Services, please contact us. You must also be at least 16 years of age to consent to the processing of your personally identifiable information in your country (in some countries we may allow your parent or guardian to do so on your behalf).

Changes to This Privacy Policy

I may update our Privacy Policy from time to time. Thus, you are advised to review this page periodically for any changes. I will notify you of any changes by posting the new Privacy Policy on this page.

This policy is effective as of 2022-08-09

Contact Us

If you have any questions or suggestions about my Privacy Policy, do not hesitate to contact me at mimic@cheekyghost.com