You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.07 16:12:30