Test support

The SDK makes it easy to write unit, integration, UI, or other types of automated tests in your code base. We designed our SDK with first-class support for automated testing, making it easy to inject dependencies and perform mocking in your code.

This page is part of a setup flow for the SDK. Before you continue, make sure you've implemented previous features—i.e. you can't receive in-app notifications before you identify people!

graph LR getting-started(Install SDK) -->B(Initialize SDK) B --> identify(identify people) identify -.-> track-events(Send events) identify -.-> register-token(Register
Device Token) register-token -.-> push(Receive push) register-token -.-> rich-push(Receive Rich Push) track-events --> test-support(Write tests) push --> test-support rich-push --> test-support identify -.-> in-app(Receive in-app) in-app --> test-support click getting-started href "/docs/sdk/ios/getting-started/#install" click B href "/docs/sdk/ios/getting-started/#initialize-the-sdk" click identify href "/docs/sdk/ios/identify" click track-events href "/docs/sdk/ios/track-events/" click register-token href "/docs/sdk/ios/push" click push href "/docs/sdk/ios/push" click rich-push href "/docs/sdk/ios/rich-push" click in-app href "/docs/sdk/ios/in-app" click test-support href "/docs/sdk/ios/test-support" style test-support fill:#B5FFEF,stroke:#007069

Dependency injection

Every SDK class inherits from a Swift protocol. Inherited protocols use a consistent naming convention: <NameOfClass>Instance. For example, the CustomerIO class inherits the protocol CustomerIOInstance.

If you want to inject a class in your project, it could look something like the example below.

import CioTracking

class ProfileRepository {
    private let cio: CustomerIOInstance

    init(cio: CustomerIOInstance) {
        self.cio = cio

    // Now, you can call any of the `CustomerIO` class functions with `self.cio`!
    func loginUser(email: String, password: String, onComplete: @escaping (Result<Success, Error>) -> Void) {
        // Login the user to your system...

        // Then, identify the profile with Customer.io:
        self.cio.identify(identifier: email)

// Inject an instance of the `CustomerIO` class to your class:
let cio = CustomerIO(...)
let repository = ProfileRepository(cio: cio)


The Customer.io SDK comes bundled with mock classes ready for you to use. That’s right, we generated mocks for you!

Mock classes follow the naming convention: <NameOfClass>Mock. For example, mock the CustomerIO class with CustomerIOMock.

Here’s an example test class showing how you would test your ProfileRepository class.

import Foundation
import CioTracking
import XCTest

class ProfileRepositoryTest: XCTestCase {
    private var cioMock: CustomerIOMock!
    private var repository: ProfileRepository!

    override func setUp() {

        cioMock = CustomerIOMock() // Create a new instance of the mock in setUp() to reset the mock. 

        repository = ProfileRepository(cio: cioMock)

    func test_loginUser() {
        // Now, call your function under test:

        // You can access many properties of the mock class to assert the behavior of the mock. 
        XCTAssertEqual(cioMock.identifyBodyCallsCount, 1)
        XCTAssertEqual(cioMock.identifyBodyReceivedInvocations[0].identifier, expectedIdentifier) 
Copied to clipboard!
Current release
Is this page helpful?