Swift 使用SingleValueDecodingContainer对可解码的一致性进行单元测试

Swift 使用SingleValueDecodingContainer对可解码的一致性进行单元测试,swift,unit-testing,codable,decodable,Swift,Unit Testing,Codable,Decodable,所以,我有一种类型,看起来像这样: struct Identifier { let string: String } extension Identifier: Decodable { public init(from decoder: Decoder) throws { let container = try decoder.singleValueContainer() string = try container.decode(String.

所以,我有一种类型,看起来像这样:

struct Identifier {
    let string: String
}

extension Identifier: Decodable {
    public init(from decoder: Decoder) throws {
        let container = try decoder.singleValueContainer()
        string = try container.decode(String.self)
    }
}
{
    "identifier": "abc123",
    // more properties ...
}
func testDecodableInit() {
    let identifier = try! JSONDecoder().decode(Identifier.self, from: "1".data(using: .utf8)!)
    XCTAssertEqual(identifier.string, "1")
}
这种类型的要点是,如果我有如下的JSON:

struct Identifier {
    let string: String
}

extension Identifier: Decodable {
    public init(from decoder: Decoder) throws {
        let container = try decoder.singleValueContainer()
        string = try container.decode(String.self)
    }
}
{
    "identifier": "abc123",
    // more properties ...
}
func testDecodableInit() {
    let identifier = try! JSONDecoder().decode(Identifier.self, from: "1".data(using: .utf8)!)
    XCTAssertEqual(identifier.string, "1")
}
。。。它将自动序列化为正确的类型,无需花费太多精力。但是,在没有创建包装类型的情况下,我很难对这种与
可解码的
的一致性进行单元测试

我想做的是这样的:

struct Identifier {
    let string: String
}

extension Identifier: Decodable {
    public init(from decoder: Decoder) throws {
        let container = try decoder.singleValueContainer()
        string = try container.decode(String.self)
    }
}
{
    "identifier": "abc123",
    // more properties ...
}
func testDecodableInit() {
    let identifier = try! JSONDecoder().decode(Identifier.self, from: "1".data(using: .utf8)!)
    XCTAssertEqual(identifier.string, "1")
}
但显然这不起作用,因为
“1”
不是有效的JSON


有没有可能在不创建包装类型并将数据更改为有效的JSON的情况下编写一个符合
Decodable
的单元测试呢?

我放弃了在不创建包装类型的情况下完成这项工作,因为假设很难解码一个从一开始就不是有效的JSON的字符串(
'1'
在我的示例中)


所以,我想,答案是:只需创建一种包装类型。”\_(ツ)_/“

如果有人想知道如何使用包装类型创建测试,它看起来是这样的

struct Identifier {
    let string: String
}

extension Identifier: Decodable {
    public init(from decoder: Decoder) throws {
        let container = try decoder.singleValueContainer()
        string = try container.decode(String.self)
    }
}
class IdentifierTests: XCTestCase {

    func testStringValueDecodedSuccessfully() throws {
        let decoder = JSONDecoder()
        let data = Data("{\"value\": \"identifier-string\"}".utf8)
        let container = try decoder.decode(Wrapper1.self, from: data)
        XCTAssertEqual(container.identifierValue.string, "identifier-string")
    }
}

private struct Wrapper: Decodable {

    let identifierValue: Identifier

    enum CodingKeys: String, CodingKey {
        case value
    }

    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        identifierValue = try container.decode(Identifier.self, forKey: .value)
    }
}
我们的测试是这样的

struct Identifier {
    let string: String
}

extension Identifier: Decodable {
    public init(from decoder: Decoder) throws {
        let container = try decoder.singleValueContainer()
        string = try container.decode(String.self)
    }
}
class IdentifierTests: XCTestCase {

    func testStringValueDecodedSuccessfully() throws {
        let decoder = JSONDecoder()
        let data = Data("{\"value\": \"identifier-string\"}".utf8)
        let container = try decoder.decode(Wrapper1.self, from: data)
        XCTAssertEqual(container.identifierValue.string, "identifier-string")
    }
}

private struct Wrapper: Decodable {

    let identifierValue: Identifier

    enum CodingKeys: String, CodingKey {
        case value
    }

    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        identifierValue = try container.decode(Identifier.self, forKey: .value)
    }
}

此测试的目标是什么?验证是否为无效/不正确的JSON引发错误?是的,JSON中表示的字符串可以转换为
标识符