在单元测试中模拟UserDefaults对象返回_ArrayBuffer

时间:2017-08-02 04:15:11

标签: ios xcode unit-testing swift3 mocking

我试图在单元测试中删除对象对象(如URLSessions和UserDefaults)的依赖关系。我试图将预先缓存的数据模拟到我为测试目的而制作的模拟UserDefaults对象中。

我创建了一个具有编码和解码功能的测试类,并将模拟数据存储在成员变量中,该变量是[String:AnyObject]字典。在我的应用程序中,在启动时它将检查缓存中的数据,如果找到,则跳过网络调用。

所有我能够得到的都是零或这一个持续的错误:

  

致命错误:NSArray元素无法与Swift数组元素匹配   型

查看调试器,解码器应该返回一个自定义类型的数组" Question"。相反,我得到一个_ArrayBuffer对象。

如果我的应用程序将数据加载到我的模拟userdefaults对象中,它也很奇怪,它运行正常,但当我将对象硬编码到其中时,我收到此错误。

这是我的模拟UserDefaults对象的代码:

class MockUserSettings: DataArchive {
    private var archive: [String: AnyObject] = [:]

    func decode<T>(key: String, returnClass: T.Type, callback: (([T]?) -> Void)) {
        print("attempting payload from mockusersettings with key: \(key)")
        if let data = archive[key] {
            callback(data as! [T])
        } else {
            print("Found nothing for: \(key)")
            callback(nil)
        }
    }

    public func encode<T>(key: String, payload: [T]) {
        print("Adding payload to mockusersettings with key: \(key)")
        archive[key] = payload as AnyObject
    }
}

我试图通过测试:

func testInitStorageWithCachedQuestions() {
    let expect = XCTestExpectation(description: "After init with cached questions, initStorage() should return a cached question.")

    let mockUserSettings = MockUserSettings()
    var questionsArray: [Question] = []
    for mockQuestion in mockResponse {
        if let question = Question(fromDict: mockQuestion) {
            questionsArray.append(question)
        }
    }
    mockUserSettings.encode(key: "questions", payload: questionsArray)
    mockUserSettings.encode(key: "currentIndex", payload: [0])
    mockUserSettings.encode(key: "nextFetchDate", payload: [Date.init().addingTimeInterval(+60)])

    let questionStore = QuestionStore(dateGenerator: Date.init, userSettings: mockUserSettings)

    questionStore.initStore() { (question) in
        let mockQuestionOne = Question(fromDict: self.mockResponse[0])
        XCTAssertTrue(question == mockQuestionOne)
        XCTAssert(self.numberOfNetworkCalls == 0)
        expect.fulfill()
    }
    wait(for: [expect], timeout: 1.0)
}

如果有人可以帮助我绕过我做错的事情,我将不胜感激。我正确存储我的模拟对象吗?什么是这个ArrayBuffer和ArrayBridgeStorage的东西??

1 个答案:

答案 0 :(得分:0)

我解决了我的问题。我的自定义课程同时针对我的应用和测试。在单元测试中,我使用的是我的类构造函数的测试目标版本,而不是我的主应用程序的版本。

因此,除此之外的教训就是使用@testable import而不是让您的应用类定位测试。