Swift 2.0 Unit Testing for NSCoding
Asked Answered
H

3

6

I am going to try and use the new testing features in Xcode 7 (code coverage) and Swift 2.0.

Using code coverage, I see that I am not testing my NSCoding methods.

enter image description here

For a trivial example of saving a few details, such as:

required init(coder aDecoder: NSCoder) {
    name = aDecoder.decodeObjectForKey("name") as! String
    time = aDecoder.decodeIntegerForKey("time")
}

func encodeWithCoder(aCoder: NSCoder) {
    aCoder.encodeInteger(time, forKey: "time")
    aCoder.encodeObject(name, forKey: "name")
}

How do I go about testing these methods in an XCTest class.

Heteronym answered 15/8, 2015 at 23:34 Comment(0)
H
12

Walking away from a problem always helps.

func testDecoder() {

    let path = NSTemporaryDirectory() as NSString
    let locToSave = path.stringByAppendingPathComponent("teststasks")

    let newTask = Task(name: "savename", time: "10")

    // save tasks
    NSKeyedArchiver.archiveRootObject([newTask], toFile: locToSave)

    // load tasks
    let data = NSKeyedUnarchiver.unarchiveObjectWithFile(locToSave) as? [Task]

    XCTAssertNotNil(data)
    XCTAssertEqual(data!.count, 1)
    XCTAssertEqual(data!.first?.name, "savename")
    XCTAssertEqual(data!.first?.time, 10)
}
Heteronym answered 16/8, 2015 at 3:1 Comment(2)
To complete this I'd add file removal at the end of the test. While it is in the temp directory, it doesn't have to be purged and unit tests shouldn't leave any state changed.Pageantry
Fixed some of the deprecation warnings: let locToSave = path.appendingPathComponent("tests_partners") NSKeyedArchiver.archiveRootObject(newPartner, toFile: locToSave) let data = NSKeyedUnarchiver.unarchiveObject(withFile: locToSave) as?Wizardry
L
3

Improving @DogCoffee answer a bit, in case you don't want to create actual files during tests and just instead encode and decode to a simple Data memory based buffer:

func testDecoder() throws {
    let savedTask = Task(name: "savename", time: "10")

    let encodedData = try NSKeyedArchiver.archivedData(withRootObject: [savedTask], requiringSecureCoding: false)
    let loadedTasks = try XCTUnwrap(try NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(encodedData) as? [Task])

    XCTAssertEqual(loadedTasks.count, 1)
    let loadedTaks = loadedTasks.first! 

    XCTAssertEqual(loadedTask.name, "savename")
    XCTAssertEqual(loadedTask.time, 10)
}

This also uses the newer XCTUnwrap(expression) API to assert that an expression is not nil, and then return the unwrapped value.

Lineolate answered 11/10, 2021 at 14:57 Comment(0)
W
2

The above answer (@dogcoffee's) is correct, adding some deprecation warnings that I've fixed

let locToSave = path.appendingPathComponent("teststasks")

NSKeyedArchiver.archiveRootObject(newPartner, toFile: locToSave)

let data = NSKeyedUnarchiver.unarchiveObject(withFile: locToSave) as? YourClass
Wizardry answered 17/8, 2019 at 23:0 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.