Создать временный файл в модульном тесте Swift - PullRequest
1 голос
/ 03 мая 2019

Я хочу написать модульный тест для чтения / записи файлов, поэтому я создал вспомогательный функционал, который создает временный файл (адаптированный из Документы Apple ):

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
}

Проблема в том, что createFile линия ближе к концу. Это всегда терпит неудачу! У модульных тестов нет разрешения на запись во временный каталог?

Если я проигнорирую этот сбой и попытаюсь записать в файл

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

При попытке открыть дескриптор файла появляется ошибка, что файл не существует.

Нужно ли где-то настраивать разрешения на запись в файл для моего модульного теста?

Ответы [ 2 ]

1 голос
/ 03 мая 2019

Файл не может быть создан, так как по этому URL / пути уже существует каталог, который был создан fileManager.createDirectory(at: fileURL, ...). Вы можете подтвердить это, добавив эти утверждения, чтобы проверить, что существует в fileURL после вызова 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)

Чтобы иметь возможность создать файл на fileURL, вы хотите создать только его родительский каталог:

try fileManager.createDirectory(at: fileURL.deletingLastPathComponent(), withIntermediateDirectories: true)
0 голосов
/ 04 мая 2019

Когда вы создаете файлы в модульных тестах, вы нарушаете принципы FIRST.Вместо этого я бы смоделировал поведение файловой системы следующим образом:

protocol FileSystemProtocol {
    func createDirectory(_ url: URL) throws
    func deleteDirectory(_ url: URL) throws
    // readFile, writeFile etc
}

class FileSystemMock: FileSystemProtocol {
    var directoryUrls = Set<URL>()

    func createDirectory(_ url: URL) throws {
        self.directoryUrls.insert(url)
    }

    func deleteDirectory(_ url: URL) throws {
        self.directoryUrls.remove(url)
    }
}

// setup
let fileSystemMock = FileSystemMock()
let testableObject = TestableClass(fileSystemMock)

// test testableMethod
XCTAssertNoThrow(try testableObject.testableMethod())
XCTAssert(fileSystemMock.directoryUrls.count == 1)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...