Skip to content

Instantly share code, notes, and snippets.

@asharov
Last active May 23, 2020 10:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save asharov/8c2010c07242528326e10e528f429065 to your computer and use it in GitHub Desktop.
Save asharov/8c2010c07242528326e10e528f429065 to your computer and use it in GitHub Desktop.
Two helper matchers for Nimble to test that a Swift Codable implementation round-trips through its decode-encode and encode-decode cycles
import Foundation
import Nimble
public func roundTripFromJson<T: Codable>(throughType type: T.Type) -> Predicate<Data> {
return Predicate { (actualExpression: Expression<Data>) throws -> PredicateResult in
guard let initialData = try actualExpression.evaluate() else {
return PredicateResult(status: .fail, message: .fail("expected a non-<nil> Data"))
}
let object = try JSONDecoder().decode(type, from: initialData)
let encodedData = try JSONEncoder().encode(object)
let initialJson = try JSONSerialization.jsonObject(with: initialData, options: .allowFragments) as! NSObject
let encodedJson = try JSONSerialization.jsonObject(with: encodedData, options: .allowFragments) as! NSObject
let message = ExpectationMessage.expectedCustomValueTo("equal as JSON <\(String(data: initialData, encoding: .utf8)!)>", String(data: encodedData, encoding: .utf8)!)
return PredicateResult(bool: initialJson.isEqual(encodedJson), message: message)
}
}
public func roundTripThroughJson<T: Codable & Equatable>() -> Predicate<T> {
return Predicate { (actualExpression: Expression<T>) throws -> PredicateResult in
guard let object = try actualExpression.evaluate() else {
return PredicateResult(status: .fail, message: .fail("expected a non-<nil> object"))
}
let json = try JSONEncoder().encode(object)
let decodedObject = try JSONDecoder().decode(T.self, from: json)
let message = ExpectationMessage.expectedCustomValueTo("equal <\(String(describing: object))>", String(describing: decodedObject))
return PredicateResult(bool: decodedObject == object, message: message)
}
}
// MyType is our own type that conforms to Codable
// Testing round trip through the decode-encode cycle
let data = ...
expect(data).to(roundTripFromJson(throughType: MyType.self))
// Testing round trip through the encode-decode cycle
// Note: MyType must conform to Equatable in addition to Codable
let myObject = MyType(...)
expect(myObject).to(roundTripThroughJson())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment