Mock Generator Development With Using Mockolo Library

Beyza Ince
Trendyol Tech
Published in
6 min readMay 17, 2023

As the iOS team at Trendyol, we write unit tests for the logic implemented in presenter or manager classes. To ensure stability in all scenarios, we inject all classes into the presenter. When it comes to unit testing, we then mock all the classes within the presenter.

In this article, we’ll share our journey at Trendyol’s iOS team, where we encountered challenges with our previous mock generator, MockGeneratorForXcode, and transitioned to using Mockolo, an actively maintained library developed by Uber. We’ll explain how we developed a customized Xcode extension tool with Mockolo to align it with our existing workflow. This walkthrough covers creating the extension application, defining its functionality, accessing the protocol path, and modifying the mock generation code. By the end, you’ll gain insights into how we overcame our challenges and acquire knowledge that can be applied to similar situations in your own projects.

Problems

Previously, we used to generate mock classes with MockGeneratorForXcode. Unfortunately, this library has stopped being developed for new features. Consequently, we started to search for a new mock generator that could automatically generate functions and protocols with asynchronous definitions and also classes which in hidden folders. During our research we discovered the Mockolo library, developed by Uber, which not only addresses our needs but is also actively maintained.

Mockolo

Mockolo allows for the mocking of protocols on specific paths via a command-line interface (CLI). We decided to customize its usage due to its divergent approach from the existing structure within our team’s workflow. As a result, we developed an extension in a higher layer, enabling the team to continue the usage they are used to.

During the development of this application, we examined the MockGeneratorForXcode library and got help in the necessary parts. In the following section, let’s see how we implemented this extension.

Creating an Extension Application

To develop an Xcode extension tool, we need to first create an application.
Subsequently, we need to add the Xcode Source Editor extension as a new target to the application we have created. This allows us to create the extension that will be displayed within Xcode.

To ensure the secure usage of the extension, we must also include the Sandbox from the Capability section. (Sandbox is a feature that generally restricts the access of applications on the system.) Additionally, the extension we develop needs to listen to the thread on which Xcode is running. For this purpose, we must also enable Apple Events in the Hardened Runtime section.

Getting the Project Path

The developer can’t run the extension without giving the user permission to the project path where the extension will be used. To achieve this, we need to define the App Groups, which will be shared between the app and extension targets. It is recommended to start with the “group” prefix as a common convention.

On the application side, we need to prompt the user to select the project path and ensure that the chosen path is registered in the User Defaults using the designated path within the App Groups. This User Defaults data will be shared and utilized when running the extension. To achieve this, we need to create bookmark data for the selected path and save it to User Defaults.

Creating Extension Button

Now we reach the step of running the extension. To accomplish this, we need to begin by defining the data that we want to display as a button in our extension in the Info.plist file.

As our extension is solely dedicated to the Mock generation command, we have made a singular definition for its functionality.

Upon pressing the “Generate Mock” button, the perform function in the class will automatically execute. The invocation parameter in this function allows access to all the code within the class where the extension is running. This enables us to access the desired protocol that we want to generate a mock for.

Real World Example

For example, let’s generate the MockBasketInteractor class.

First, we find the BasketInteractorInterface protocol over invocation.

We do not have information about the specific file in the project where the specified protocol is located. To determine this, we need to access all the project files and search for the protocol. To achieve this, we first need to access the Workspace that is open in Xcode. The code snippet below demonstrates how to accomplish this by running a script and accessing the relevant workspace.

Once we have successfully accessed the Workspace, our next step is to scan through all the files and gather the ones with a “.swift” extension.

In order to verify the presence of the relevant protocol within the swift files we have accessed, we execute the following function.

All the work so far has been to find the protocol path. In the following section, we will talk about how we tailor the organization to align with our workflow.

Due to the disparity between our mock structure and the Mockolo library, we needed to modify the code responsible for generating mocks within the library.

To achieve this, we made the Executor class in Mockolo public and transformed it into a structure that can be accessed within our own project. This allows us to conveniently pass the protocol path as a parameter to the Executor and generate the mock with ease.

CLI Part

As a result of the aforementioned process, the mock class we generate will be stored in the Output class. As we cannot directly perform the generation operation within the class, we temporarily write the output.swift file within the extension. The next step involves writing the mock data from this class to the corresponding class within the project.

To generate the mock, we write the mock file created in the above function into the targeted class within the project. We utilize the invocation parameter for this write operation as well. After completing all of these steps, the final version of the class we created for mock generation is as follows. This Mock structure is tailored specifically for SwiftyKit, which we developed within our team.

In conclusion, we have developed an up-to-date library to address the issues related to mocking within our team. If you have any further adjustments or specific requirements for the concluding paragraph, please let me know!

If you want to be part of a team that tries new technologies and want to experience a new challenge every day, come to us.

--

--