Max
Max

Reputation: 22385

Create temp file in Swift unit test

I want to write a unit test that reads/writes files, so I made a helper func that makes a tempfile (adapted from Apple's docs):

func mkTmp() -> URL {
    let fileManager = FileManager.default
    let directory = fileManager.temporaryDirectory
    let filename = UUID().uuidString
    let fileURL = directory.appendingPathComponent(filename)

    addTeardownBlock {
        do {
            if fileManager.fileExists(atPath: fileURL.path) {
                try fileManager.removeItem(at: fileURL)
                XCTAssertFalse(fileManager.fileExists(atPath: fileURL.path))
            }
        } catch {
            XCTFail("Error while deleting temporary file: \(error)")
        }
    }

    do {
        try fileManager.createDirectory(at: fileURL, withIntermediateDirectories: true)
        // FIXME: this always fails for some reason
        XCTAssertTrue(fileManager.createFile(atPath: fileURL.path, contents: "test".data(using: .utf8)))
    } catch {
        XCTFail("Error while making temp dir: \(error)")
    }
    return fileURL
}

The problem is that createFile line near the end. It always fails! Do unit tests not have write permissions on the temporary directory?

If I ignore that failure and just try to write to the file

let file = try FileHandle(forWritingTo: mkTmp())
defer { file.closeFile() }
file.write(data)

I get an error that the file doesn't exist when I try to open the file handle.

Do I need to set up file writing permissions somewhere for my unit test?

Upvotes: 5

Views: 4559

Answers (1)

David Rönnqvist
David Rönnqvist

Reputation: 56635

The file cannot be created because a directory already exist at that url/path—which was created by fileManager.createDirectory(at: fileURL, ...). You can confirm this by adding these assertions to check what exists at fileURL after calling fileManager.createDirectory(at: fileURL, ...):

try fileManager.createDirectory(at: fileURL, withIntermediateDirectories: true)

var isDirectory: ObjCBool = false
XCTAssertTrue(fileManager.fileExists(atPath: fileURL.path, isDirectory: &isDirectory))
XCTAssertTrue(isDirectory.boolValue)

To be able to create the file at fileURL you only want to create its parent directory:

try fileManager.createDirectory(at: fileURL.deletingLastPathComponent(), withIntermediateDirectories: true)

Upvotes: 5

Related Questions