kezor
kezor

Reputation: 101

Could not cast value of type 'FIRTimestamp' to 'FIRTimestamp'

I'm trying to write some unit tests for some model objects I'm developing. I'm seeing some strange unexpected behavior when getting Timestamps out of an dictionary [String:Any]. The timestamp is nil when trying to cast to a non-optional. But you can see in the print outputs that it's a timestamp. Does anyone have any ideas?

The output of the two print statements is:

nil
Optional(<FIRTimestamp: seconds=1562802592 nanoseconds=1123>)

import XCTest
import Firebase

@testable import MyTarget

class UserTest: XCTestCase {

    var testDict:[String : Any]? = [:]

    var renewalDate:Timestamp = Timestamp(seconds: Int64(1562802592), nanoseconds: Int32(1123))

    override func setUp() {
        super.setUp()
        testDict = [
            "userId": "userId",
            "firstName": "J",
            "lastName" : "R",
            "email": "[email protected]",
            "renewalDate": renewalDate
        ]
    }

func testInit_ReturnsInstanceWhenRequiredPropertiesAreSpecificed() {
        let zUser = ZenUser(dictionary: testDict)
        XCTAssertNotNil(zenUser, "ZenUser should not be nil")
}
}
ZenUser : DocumentDeserializable {
    init?(dictionary:[String:Any]?) {
        let t = dictionary?["renewalDate"] as? Timestamp
        print(t)
        print(dictionary?["renewalDate"])
        guard let userId = dictionary?["userId"] as? String,
            let firstName = dictionary?["firstName"] as? String,
            let renewalDate = dictionary?["renewalDate"] as? Timestamp,
            let lastName = dictionary?["lastName"] as? String else {
                print("Missing fields, returning nil")
                return nil
        }

...

}

protocol DocumentDeserializable {
    init?(dictionary: [String: Any]?)
}

Why is the timestamp nil when casting to non-optional?

Here are the versions I'm using.

Using Firebase (6.4.0)
Using FirebaseABTesting (3.0.0)
Using FirebaseAnalytics (6.0.3)
Using FirebaseAuth (6.2.0)
Using FirebaseAuthInterop (1.0.0)
Using FirebaseCore (6.0.4)
Using FirebaseFirestore (1.4.1)

Upvotes: 4

Views: 890

Answers (1)

cybergen
cybergen

Reputation: 3157

Workaround: Create the Timestamp in your app code rather than the test code. I needed a Timestamp from a Date, so I created this extension (in the app code) and use it in my tests.

Date extension (Date+Timestamp.swift):

import FirebaseFirestore

extension Date {
    
    var timestamp: Timestamp {
        Timestamp(date: self)
    }

    // add more extensions upon need
}

Add the Date extension to your app target(s), not to the test target.

Part of the test:

let data: [String: Any] = [
    Receipt.Keys.date.rawValue: Date().timestamp
]

This way the tested code can properly cast the object to a Timestamp.

Upvotes: 1

Related Questions