How to resolve error in unit testing when we have Date comparison in Codable

泪湿孤枕 提交于 2020-02-29 09:22:36

问题


I tried to use custom date strategy in json decoding using Codable as describe in https://stackoverflow.com/a/28016692/3477974 . Here is the simplified implementation code:

public extension Formatter {
    static let iso8601: DateFormatter = {
        let formatter = DateFormatter()
        formatter.calendar = Calendar(identifier: .iso8601)
        formatter.locale = Locale(identifier: "en_US_POSIX")
        formatter.timeZone = TimeZone(secondsFromGMT: 0)
        formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSXXXXX"
        return formatter
    }()
}

public extension Date {
    var iso8601: String {
        return Formatter.iso8601.string(from: self)
    }
}


public extension JSONDecoder.DateDecodingStrategy {
    static let iso8601withFractionalSeconds = custom {
        let container = try $0.singleValueContainer()
        let string = try container.decode(String.self)
        guard let date = Formatter.iso8601.date(from: string) else {
            throw DecodingError.dataCorruptedError(in: container,
                  debugDescription: "Invalid date: " + string)
        }
        return date
    }
}


public extension JSONEncoder.DateEncodingStrategy {
    static let iso8601withFractionalSeconds = custom {
        var container = $1.singleValueContainer()
        try container.encode(Formatter.iso8601.string(from: $0))
    }
}

However, when it comes to unit testing it fails although the error message shows equal value used by description method of date:

    func test_jsonCodable_iso8601() {
        let dates = [Date()] // ["Feb 9, 2020 at 12:55:24 PM"]

        let encoder = JSONEncoder()
        encoder.dateEncodingStrategy = .iso8601withFractionalSeconds
        let data = try! encoder.encode(dates)

        let decoder = JSONDecoder()
        decoder.dateDecodingStrategy = .iso8601withFractionalSeconds
        let decodedDates = try! decoder.decode([Date].self, from: data) // ["Feb 9, 2020 at 12:55:24 PM"]

        XCTAssertEqual(dates, decodedDates)
        // fails with error message: [2020-02-09 12:55:24 +0000]") is not equal to ("[2020-02-09 12:55:24 +0000]"
    }

Do you have any idea what is the issue and how we can resolve it?

By the way, the actual decodable object is the following one where publishedAt is of type date:

public struct NewsItem: Equatable {
    public let id: UUID
    public let author: String
    public let title: String
    public let description: String
    public let urlToImage: URL?
    public let publishedAt: Date
    public let content: String

    public init(id: UUID,
                author: String,
                title: String,
                description: String,
                urlToImage: URL?,
                publishedAt: Date,
                content: String) {

        self.id = id
        self.author = author
        self.title = title
        self.description = description
        self.urlToImage = urlToImage
        self.publishedAt = publishedAt
        self.content = content
    }
}

extension NewsItem: Decodable {}

回答1:


What you are testing is the date/string conversion so there is no need to involve JSON encoding and decoding into this. Start with a fixed date in string form, convert it to date and back and check the end result vs the fixed date

let input = "2020-02-02T19:10:23.123Z"

let formatter = DateFormatter.iso8601
let date = formatter.date(from: input)
let output = date?.iso8601

print(date != nil && input == output!)

Note that this was written in a playground and not as a unit test



来源:https://stackoverflow.com/questions/60136982/how-to-resolve-error-in-unit-testing-when-we-have-date-comparison-in-codable

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!