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

单元测试覆盖率低于预期,如何完善JSON转Data工具类测试?

Boosting Unit Test Coverage for Your JSON-to-Data Utility Method

Got it, let's walk through how to beef up your unit tests and fix a couple of small issues in your utility code to get better coverage and more reliable tests.

First, Refactor the Utility Method for Better Swift Compatibility

Your current method uses [String : AnyObject] as the parameter type, which is a holdover from Objective-C compatibility. In modern Swift, JSONSerialization works perfectly with [String : Any] (since JSON values can be strings, numbers, booleans, arrays, dictionaries, or nil), so let's update that to avoid unnecessary type casting:

static func data(from json: [String : Any]) throws -> Data {
    return try JSONSerialization.data(withJSONObject: json, options: .prettyPrinted)
}

(Note: You don't need the extra do/catch block here—just rethrow the error directly. It keeps the code cleaner without changing behavior.)

Expand Test Cases to Cover All Scenarios

Right now your test only covers the happy path. To hit full coverage, you need to test failure scenarios, edge cases, and validate the correctness of the serialized data (not just that it exists).

1. Improve the Success Path Test

Instead of just checking that data isn't nil, verify that the serialized data can be deserialized back to match the original JSON. This ensures the serialization actually works as expected:

func testJsonToDataSuccessAndAccurate() {
    let testJson: [String : Any] = [
        "greeting": "Hello, World!",
        "age": 30,
        "isActive": true,
        "hobbies": ["reading", "coding"],
        "contact": ["email": "test@example.com"]
    ]
    
    do {
        let data = try Utils.data(from: testJson)
        XCTAssertNotNil(data, "Serialized data should not be nil")
        
        // Deserialize the data back to JSON and validate matches original
        guard let deserializedJson = try JSONSerialization.jsonObject(with: data) as? [String: Any] else {
            XCTFail("Failed to deserialize data back to JSON")
            return
        }
        
        XCTAssertEqual(deserializedJson["greeting"] as? String, testJson["greeting"] as? String)
        XCTAssertEqual(deserializedJson["age"] as? Int, testJson["age"] as? Int)
        XCTAssertEqual(deserializedJson["isActive"] as? Bool, testJson["isActive"] as? Bool)
        XCTAssertEqual(deserializedJson["hobbies"] as? [String], testJson["hobbies"] as? [String])
        XCTAssertEqual(deserializedJson["contact"] as? [String: String], testJson["contact"] as? [String: String])
    } catch {
        XCTFail("Unexpected error during serialization: \(error.localizedDescription)")
    }
}

2. Add Failure Scenario Tests

JSONSerialization throws errors when given non-serializable objects (like Date, custom classes, or cyclical references). Let's test these cases:

func testJsonToDataFailureWithInvalidObjects() {
    // Test with a non-serializable Date object
    let invalidJsonWithDate: [String: Any] = ["lastLogin": Date()]
    XCTAssertThrowsError(try Utils.data(from: invalidJsonWithDate)) { error in
        guard let jsonError = error as? NSError else {
            XCTFail("Expected JSONSerialization error, got \(type(of: error))")
            return
        }
        XCTAssertEqual(jsonError.code, JSONSerialization.ErrorCode.invalidJSONObject.rawValue)
    }
    
    // Test with cyclical reference (dictionary references itself)
    var cyclicalJson: [String: Any] = [:]
    cyclicalJson["selfReference"] = cyclicalJson
    XCTAssertThrowsError(try Utils.data(from: cyclicalJson))
}

3. Test Edge Cases

Don't forget edge cases like empty dictionaries, strings with special characters, or nil values:

func testJsonToDataEdgeCases() {
    // Empty dictionary
    let emptyJson: [String: Any] = [:]
    do {
        let data = try Utils.data(from: emptyJson)
        XCTAssertNotNil(data)
        let deserialized = try JSONSerialization.jsonObject(with: data) as? [String: Any]
        XCTAssertEqual(deserialized?.count, 0)
    } catch {
        XCTFail("Empty dictionary should serialize successfully")
    }
    
    // String with special characters
    let specialCharJson: [String: Any] = ["message": "Line 1\nLine 2 🌍 \\\"Quoted Text\\\""]
    do {
        let data = try Utils.data(from: specialCharJson)
        XCTAssertNotNil(data)
        guard let deserialized = try JSONSerialization.jsonObject(with: data) as? [String: Any],
              let message = deserialized["message"] as? String else {
            XCTFail("Failed to deserialize special character string")
            return
        }
        XCTAssertEqual(message, "Line 1\nLine 2 🌍 \\\"Quoted Text\\\"")
    } catch {
        XCTFail("Special character string should serialize successfully")
    }
}

Why This Works

By expanding your tests to cover:

  • The happy path (with validation of serialized content)
  • Failure scenarios (invalid objects, cyclical references)
  • Edge cases (empty data, special characters)

You'll hit 100% test coverage for your utility method, and your tests will catch more potential issues in the future. The refactor to [String: Any] also makes the method easier to use without type casting.

内容的提问来源于stack exchange,提问作者ridvankucuk

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 06:24:27