我正在尝试为用Swift 2.2编写的个人项目编写单元测试。该项目的一部分是自定义类LocalStorageManager,该类使用NSFileManager来执行文件IO操作并公开非常简化的文件交互,以供其他应用程序访问。现在,我需要模拟NSFileManager,因为我不希望我的测试创建真实文件。我一直在尝试一些东西,但是我不喜欢它。

我用以下格式编写了一个模拟类:

import Foundation

class MockNSFileManager: NSFileManager {

    override init() {
        // do nothings master!!
    }

    override func createFileAtPath(path: String, contents data: NSData?, attributes attr: [String : AnyObject]?) -> Bool {
        print("file mock created")
        return true
    }

    override func fileExistsAtPath(path: String, isDirectory: UnsafeMutablePointer<ObjCBool>) -> Bool {
        print("does the file exists?")
        return false
    }

    override func fileExistsAtPath(path: String) -> Bool {
        print("the file exists")
        return true
    }

    override func createDirectoryAtPath(path: String, withIntermediateDirectories createIntermediates: Bool, attributes: [String : AnyObject]?) throws {
        print("successfully maybe...")
    }

    override func contentsAtPath(path: String) -> NSData? {
        print("returning some fancy contents")
        return NSData()
    }

    override func removeItemAtPath(path: String) throws {
        print("removing item at the path")
    }
}


LocalStorageManager中,我实现了init(fileManager: NSFileManager)

在单元测试中,我将LocalStorage初始化为LocalStorage(fileManager: MockNSFileManager())

一切都按预期进行。但是,我不喜欢测试代码如何入侵我的应用产品代码。在LocalStorage类中,当我的应用不需要运行它时,我不喜欢实现init的方式。

我正在寻找一种方法,可以将模拟系统库注入我的自定义类中,以方便测试,而无需实际让测试代码侵入主应用程序代码。

最佳答案

我解决了问题!在LocalStorage类中,我先前在初始化程序中将NSFileManager实例化为fileMgr = NSFileManager()。我将初始化程序更改为init(fileManager: NSFileManager),并将NSFileManager实例分配给fileMgr。我必须在整个代码中用LocalStorage()替换对LocalStorage(NSFileManager())的调用。现在,在测试中,我只需使用模拟的NSFileManager(如LocalStorage(MockNSFileManager()))初始化LocalStorage。之所以可行,是因为从技术上讲,MockNSFileManagerNSFileManager

class MockNSFileManager: NSFileManager {

在MockFileManager类声明中。

关于ios - 如何在不使用任何模拟库的情况下模拟iOS Swift中的系统库?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/40232090/

10-08 23:51