使用 SingleValueDecodingContainer 对 Decodable 的单元测试一致性
Unit testing conformance to Decodable using a SingleValueDecodingContainer
所以,我有一个看起来像这样的类型:
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)
}
}
这种类型的要点是如果我有 JSON 看起来像这样:
{
"identifier": "abc123",
// more properties ...
}
... 它会自动序列化为正确的类型,无需太多努力。但是,我无法在不创建包装类型的情况下对 Decodable
的一致性进行单元测试。
我想做的是这样的:
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)
}
}
这种类型的要点是如果我有 JSON 看起来像这样:
{
"identifier": "abc123",
// more properties ...
}
... 它会自动序列化为正确的类型,无需太多努力。但是,我无法在不创建包装类型的情况下对 Decodable
的一致性进行单元测试。
我想做的是这样的:
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)
}
}