Sourcery — Generate Mocks for iOS Projects
Stop writing boilerplate and code that needs frequent changes!
Sourcery is a powerful code generator for Swift projects that I implemented to the project at my current job to stop writing mocks and helpers for our tests.
When I watched a presentation about Sourcery, my mind was blown thinking about how my daily code routine could be automated. That week, I spent extra hours bringing that idea to real life, and an example of the result is here.
I can’t share the code I created to use at work, but here’s an example of how powerful it is!
This article is divided into two parts. The first is an example of how it works, and the second is a deep look at the code needed to generate files.
Table of Contents
- Adding Sourcery to a project
- Create models
- Create Sourcery configuration file
- Add templates
- Create build phase script
- Let’s run
- Option to use custom default parameter at mock
1. Adding Sourcery to project
- Open Podfile
- Add the following code
- Run pod install
pod 'Sourcery', :subspecs => ['CLI-Only']
For this example, I added Sourcery using cocoapods, but you can choose any method listed on the Sourcery Installation page.
2. Create models
I create two models for this, but in a real case, you will use the models of your project. Here’s the code:
public struct Client: Codable {
public let id: Int
public let name: String
public let age: Int
public let isFistAccess: Bool
public let address: Address
}
public struct Address: Codable {
public let street: String
public let city: String
public let state: String
public let homeNumber: Int
public let postalCode: String
}
3. Create Sourcery configuration file
The Sourcery.yml is your main configuration file:
sources: the paths to include and exclude files
templates: the paths to template files
output: the path where Sourcery will write the files
args: the local variables to send to Sourcery template files
sources:
include:
- ../../SourceryExample/Models
exclude:
- ../../SourceryExampleTests
templates:
- ../Templates/ModelsMock/ModelsMock.swifttemplate
output:
../../SourceryExampleTests
args:
projectName: ${PROJECT_NAME}
- Create Sourcery.yml in the following path Meta/Configuration
- Add it to your project, then uncheck all the targets
4. Add templates
Add the Templates inside the Meta folder.
The details of Templates (ModelsMock and Core) will be described in part 2 of this article.
5. Create the build phase script
Create a new Run Script with the following code to execute Sourcery when not building for release.
#!/bin/bash
if [ "${CONFIGURATION}" != "Release" ]; then
$PODS_ROOT/Sourcery/bin/sourcery --config "${PROJECT_DIR}/Meta/Configuration/Sourcery.yml" --prune
fi
Reorder the script to execute before Compile Sources .
It’s necessary to prevent breaking the next build if the generated file breaks. With this change, the Xcode will always call “Run sourcery” to generate files before the compile project.
6. Let’s run the project
Now, it’s magic time. You need to build the project to see the newly generated file.
First, you need to import the generated file into your project:
But, for the next builds, the file will be updated automatically.
7. Option to use custom default parameter at mock
When I started adding Sourcery to my current job’s project, my biggest fear was delivering something new to my team that I was still learning about, but I wanted to reduce their workload without breaking anything, even if this new solution wasn’t 100% ready.
To prevent breaking anything, I used Sourcery Annotations to create a bypass that enabled the engineer to write the default value for the generated mock.
With this, even if the template failed to recognize the right value, the engineer could bypass and tell Sourcery the right value for that case.
This article’s code is on the main branch of my GitHub page:
https://github.com/jnevesjunior/sourceryExample
Sourcery — Generate Mocks for iOS Projects was originally published in Better Programming on Medium, where people are continuing the conversation by highlighting and responding to this story.