Unit Test class from iOS
Unit Tests should not have a dependency on the application bundle at runtime which could not be injected on the init phase or by a method arguments


The given Utility class has a static methods which act like a shortcuts to longer syntax calls. This methods calls directly methods on Bundle class object which is cannot be mocked. The solution is to move Bundle -&gt; infoDictionary outside of a method and set it as a static property. Now, in the app the dictionary can reference a dictionary from the app bundle and in test bundle will reference a mocked dictionary. The main purpose of a unit testing this methods will be to validate usage of given dictionary and keys to access demanded values.


Utility methods aka class methods are not dependency injection friendly and that makes them more complicated to test
UtilitiesMock is not a mock, it's more a proxy / facade / wrapper class


Solution:

protocol BundleInfoDictionaryShortcuts {
    static var bundleMainInfoDictionary: [String : Any]? { get set }
}

enum BundleInfoDictionary: String {
    case keyCFBundleShortVersionString = "CFBundleShortVersionString"
    case keyCFBundleVersion = "CFBundleVersion"
}

class Utilities: BundleInfoDictionaryShortcuts {

    static var bundleMainInfoDictionary: [String : Any]? = Bundle.main.infoDictionary

    static func getAppVersion() -&gt; String {

        guard let version = bundleMainInfoDictionary?[BundleInfoDictionary.keyCFBundleShortVersionString.rawValue] as? String else {
            fatalError()
        }
        return version
    }

    static func getAppBuildNumber() -&gt; String {
        guard let number = bundleMainInfoDictionary?[BundleInfoDictionary.keyCFBundleVersion.rawValue] as? String else {
            fatalError()
        }
        return number
    }
}




// File: BundleInfoDictionaryShortcutsTests.swift

class BundleInfoDictionaryShortcutsTests: XCTestCase {
        static let appVersion = "1.0.1"
        static let appBuildNumber = "120"

        override class func setUp() {
            super.setUp()
            Utilities.bundleMainInfoDictionary = [
                BundleInfoDictionary.keyCFBundleShortVersionString.rawValue: appVersion,
                BundleInfoDictionary.keyCFBundleVersion.rawValue: appBuildNumber
            ]
        }

        func testGetAppVersion() {
            XCTAssertEqual(Utilities.getAppVersion(), Self.appVersion)
        }
        func testGetAppBuildNumber() {
            XCTAssertEqual(Utilities.getAppBuildNumber(), Self.appBuildNumber)
        }
    }




// File: BundleInfoDictionaryShortcutsTests.swift

    class BundleInfoDictionaryTests: XCTestCase {
        func testKeys() {
            XCTAssertEqual(BundleInfoDictionary.keyCFBundleShortVersionString.rawValue,"CFBundleShortVersionString")
            XCTAssertEqual(BundleInfoDictionary.keyCFBundleVersion.rawValue,"CFBundleVersion")
        }
    }