Resolver for iOS Dependency Injection: Getting Started
Learn how to use Resolver to implement dependency injection in your SwiftUI iOS apps to achieve easily readable and maintainable codebases. By Mina Ashna.
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Contents
Resolver for iOS Dependency Injection: Getting Started
25 mins
- Getting Started
- Refactoring Tightly Coupled Classes
- Inversion of Control
- Understanding Dependency Flow
- Dependency Injection Without Resolver
- Dependency Injection Using Resolver
- Injecting Dependencies by Annotation
- Registering Services
- Registering Arguments
- Service Locator
- Using Scopes
- Unit Testing and the Dependency Inversion Principle
- Registering Protocols
- Generating Mock Data
- Using Resolver’s Containers
- Registering Services in a Mock Container
- Dependency Injection in Unit Tests
- Unit Testing in Action
- Where to Go From Here?
Unit Testing in Action
Open AssetServiceTests.swift. Then, in testFetchAssetsSuccessfully()
add:
// 1
let asset = mockAsset()
// 2
networkService.result = .success(assetList())
// 3
sut?.fetchAssets { assetList, error in
XCTAssertEqual(assetList?.data.count, 1)
XCTAssertEqual(assetList?.data.first, asset)
XCTAssertNil(error)
}
Here you:
- Create a mock asset. The helper method
mockAsset()
is already included in the codebase for you. You’re welcome. :] - Assert a success result to
MockNetworkService
as you test a success case. - Fetch the assets from
MockNetworkService
. Test if you receive the same asset back as you provided toMockNetworkService
.
By letting Resolver handle the dependencies, you can focus on testing AssetService
without any problems. As a result, you can add as many tests as needed.
Add the following code in testFetchAssetsFailure()
to test a failure case:
// 1
let networkError = AppError.network(description: "Something went wrong!")
// 2
networkService.result = .failure(networkError)
// 3
sut?.fetchAssets { assetList, error in
XCTAssertEqual(networkError, error)
XCTAssertNil(assetList)
}
Here you:
- Create a mock error of type
AppError
, as it’s the error type in this project. - Then create a failure result with
networkError
and pass it to theMockNetworkService
. That’s the benefit of mocking dependencies: you have complete control over the response. - Fetch the assets from
MockNetworkService
. Test if you receive the same error back as you provided toMockNetworkService
.
Good job! Run your unit test by pressing Command-U. Green is the warmest color. :]
Where to Go From Here?
You can download the completed project by clicking Download Materials at the top or bottom of the tutorial.
In this tutorial, you learned about Dependency Injection using Resolver. You can learn more about Resolver in the official GitHub repository.
You may also want to read more about using Resolver scopes.
To learn more about Dependency Injection in Swift, check out our awesome Dependency Injection Tutorial for iOS: Getting Started.
You can also read more about calling types as functions in our What’s New in Swift 5.2 article.
If you have any questions or comments, join the forum discussion below.