Elye
Elye

Reputation: 60131

How can I mock Firebase RemoteConfig for Test in iOS Swift?

I have a function that do takes in Firebase RemoteConfig

func myfunction(remoteConfig: RemoteConfig) -> String {
    if (remoteConfig["my_value"].boolValue) {
        return "ABC"
    } else {
        return "DEF"
    }
}

I try to mock the RemoteConfig, but don't know how to do it. I tried as below, and obviously, it is not working, and complaint

Cannot override 'init' which has been marked unavailable: Use +remoteConfig instead.

class MockRemoteConfig: RemoteConfig {
    public init() {}
}

class FirebaseServicesSpec : QuickSpec {
    override func spec() {
        describe("myfunction") {
            context("when my_value is not set") {
                it("is should return DEF") {
                    expect(FirebaseServices.myfunction(
                            remoteConfig: MockRemoteConfig())).to(equal("DEF"))
                }
            }
        }
    }
}

How can I mock RemoteConfig in Swift? (In Android, I can just use Mock()).

Upvotes: 0

Views: 3249

Answers (3)

Nagaraj
Nagaraj

Reputation: 43

extension RemoteConfig: RemoteConfigProtocol { }

Would demand implementation of

func configValue(forKey key: String?) -> MockRemoteConfig

Upvotes: 0

blyscuit
blyscuit

Reputation: 684

Following Jose's answer. Starting with the RemoteConfigProtocol

protocol RemoteConfigProtocol {
    func configValue(forKey key: String?) -> RemoteConfigValue // Used internally to fetch values
    subscript(_ key: String?) -> RemoteConfigValue { get } // Used to index by key like remoteConfig[key]
}

extension RemoteConfigProtocol {
    subscript(key: String?) -> RemoteConfigValue {
        return self.configValue(forKey: key)
    }
}

I add the mock for RemoteConfigValue

import Firebase

class RemoteConfigValueMock: RemoteConfigValue {

    var stringMock: String?
    var boolMock: Bool = false

    override var stringValue: String? { stringMock }
    override var boolValue: Bool { boolMock }
}

Using it as

class MockRemoteConfig: RemoteConfigProtocol {
    func configValue(forKey key: String?) -> RemoteConfigValue {
      let value = RemoteConfigValueMock()
      value.stringMock = "value"
    return value
  }
}

Upvotes: 1

Jose Tomas
Jose Tomas

Reputation: 117

I hit the same problem and the only way I've found to do this is to generate a protocol cloning the signatures of the methods I plan to use from RemoteConfig in your case all that you need is a protocol that defines the subscript function

protocol RemoteConfigProtocol {
    func configValue(forKey key: String?) -> RemoteConfigValue // Used internally to fetch values
    subscript(_ key: String?) -> RemoteConfigValue { get } // Used to index by key like remoteConfig[key]
}

extension RemoteConfigProtocol {
    subscript(key: String?) -> RemoteConfigValue {
        return self.configValue(forKey: key)
    }
}

And then extend RemoteConfig with it

extension RemoteConfig: RemoteConfigProtocol {
    // Already complies since we are cloning RemoteConfig signatures
}

After that you should use the protocol instead of RemoteConfig directly

func myfunction(remoteConfig: RemoteConfigProtocol) -> String {
    if (remoteConfig["my_value"].boolValue) {
        return "ABC"
    } else {
        return "DEF"
    }
}

And for testing

class MockRemoteConfig: RemoteConfigProtocol {
    // We have init available!

    // Protocol stubs go here
}

Hope you find this useful.

Upvotes: 3

Related Questions