Swift中Date的单元测试及JSON解码正确性验证方法咨询
解决ArticleItem中Date字段的JSON解析与测试问题
我来帮你一步步搞定这个Date字段解析的测试问题,分为解码配置和测试代码调整两部分:
第一步:配置JSONDecoder的日期解码策略
首先,你的ArticleItem需要实现Codable才能自动解析JSON,同时要处理后端字段和结构体属性的映射,还要指定正确的日期解码规则:
// 给ArticleItem添加Codable实现,处理字段映射 extension ArticleItem: Codable { enum CodingKeys: String, CodingKey { case id case description case location // 后端的"image"对应结构体的thumbnailURL case thumbnailURL = "image" // 后端的"created_date"对应结构体的created case created = "created_date" } } // 在网络层解析JSON时,配置JSONDecoder的日期解码策略 func decodeArticles(from data: Data) throws -> [ArticleItem] { let decoder = JSONDecoder() // 针对后端返回的"yyyy-MM-dd"格式,用自定义Formatter更可靠 let dateFormatter = DateFormatter() dateFormatter.dateFormat = "yyyy-MM-dd" dateFormatter.locale = Locale(identifier: "en_US_POSIX") dateFormatter.timeZone = TimeZone(secondsFromGMT: 0) // 和后端时区保持一致,通常是UTC decoder.dateDecodingStrategy = .formatted(dateFormatter) // 定义对应后端返回结构的根模型 struct RootResponse: Codable { let items: [ArticleItem] } let response = try decoder.decode(RootResponse.self, from: data) return response.items }
第二步:调整测试代码,生成正确的created_date值
测试里不能用Date()(每次运行时间不同,测试会不稳定),应该用固定日期,再转换成后端要求的字符串格式:
func test_load_deliversItemsOn200HTTPResponseWithJSONItems(){ let (sut, client) = makeSUT() // 1. 定义一个固定的测试日期(对应2020-05-09 00:00:00 UTC) let fixedTestDate = Date(timeIntervalSince1970: 1588982400) let item1 = ArticleItem( id: UUID(), description: nil, location: nil, thumbnailURL: URL(string: "http://a-url.com/")!, created: fixedTestDate ) // 2. 把固定日期转换成后端要求的"yyyy-MM-dd"格式字符串 let dateFormatter = DateFormatter() dateFormatter.dateFormat = "yyyy-MM-dd" dateFormatter.locale = Locale(identifier: "en_US_POSIX") dateFormatter.timeZone = TimeZone(secondsFromGMT: 0) let formattedDateString = dateFormatter.string(from: fixedTestDate) // 3. 构建测试用的JSON字典,注意处理可选值(nil转NSNull,避免JSONSerialization忽略字段) let item1JSON: [String: Any] = [ "id": item1.id.uuidString, "description": item1.description ?? NSNull(), "location": item1.location ?? NSNull(), "image": item1.thumbnailURL.absoluteString, "created_date": formattedDateString ] let itemsJSONDict = [ "items": [item1JSON] ] expect(sut: sut, toCompleteWithResult: .success([item1])) { let itemsJSON = try! JSONSerialization.data(withJSONObject: itemsJSONDict) client.complete(withStatusCode: 200, data: itemsJSON) } }
关键注意点
- 固定测试日期:用
Date(timeIntervalSince1970:...)生成固定时间,避免每次测试运行时间不同导致断言失败。 - Locale与时区:必须设置
en_US_POSIX和UTC时区,防止系统区域/时区设置影响日期的编码和解码。 - 可选值处理:如果结构体的可选属性是nil,要转成
NSNull,否则JSONSerialization会自动忽略该字段,和后端返回的JSON结构不一致。
内容的提问来源于stack exchange,提问作者Tung Vu Duc
相关产品推荐
相关产品推荐

