iOS - Mocking UserDefault перед загрузкой контроллера представления - PullRequest
0 голосов
/ 07 мая 2018

В настоящее время я работаю над тестом для своего приложения, и у меня возникла проблема, когда имитация пользователя по умолчанию. Позвольте мне сначала показать вам мои настройки:

вот как я высмеиваю пользователя по умолчанию:

class MockUserDefaults: UserDefaults {

    typealias FakeData = Dictionary<String, Any?>
    var data: FakeData

    convenience init() {
        self.init(suiteName: "mocking")!
    }

    override init?(suiteName suitename: String?) {
        data = FakeDefaults()
        UserDefaults().removePersistentDomain(forName: suitename!)
        super.init(suiteName: suitename)
    }

    override func object(forKey defaultName: String) -> Any? {
        if let data = data[defaultName] {
            return data
        }
        return nil
    }

    override func set(_ value: Any?, forKey defaultName: String) {
        if defaultName == "favs"{
            data[defaultName] = value
        }

    }

}

У меня в контроллере представления есть переменная userDefaults, и я установил ее так:

var userDefaults : UserDefaults {
        if (NSClassFromString("XCTest") != nil) {
            return MockUserDefaults()
        }
        return UserDefaults.standard
    }

эта переменная на самом деле является расширением протокола, которому соответствует созданный контроллер uiview, чтобы убедиться, что все мои контроллеры представления имеют эту переменную.

У меня также есть переменная в myViewcontroller, называемая favourMovie, которую я установил так:

private var favoriteMovie: Favorite? {
    if let favoriteString = userDefaults.value(forKey: "favs") as? String {
        return favorites.first(where: {$0.name == favoriteString})
    }
    return nil   
}

Теперь вот где проблема, когда я иду и пытаюсь протестировать этот контроллер представления, мне нужно установить userDefault с объектом, например:

    myviewController.userDefaults.set("avengers", forKey: "favs")

до запуска теста, но проблема в том, что переменная favourMovie всегда возвращает nil, и мне нужно, чтобы он возвращал объект до запуска теста. Любая помощь. Заранее спасибо.

ОБНОВЛЕНИЕ:

это протокол:

protocol Mockable: class {
    var userDefaults: UserDefaults { get }
}

это расширение:

extension UIViewController: Mockable {}
extension Mockable {
        var userDefaults : UserDefaults {
            if (NSClassFromString("XCTest") != nil) {
                return MockUserDefaults()
            }
            return UserDefaults.standard
        }
}

1 Ответ

0 голосов
/ 07 мая 2018

Вот два способа исправить это.

1) Делая некоторый DI. В вас viewController объявите userDefaults как неисчисляемое свойство, как показано ниже

var userDefaults : UserDefaults?

В вашем тестовом примере создайте объект MockUserDefaults, установите значения и присвойте ему значение viewController, когда вы запускаете его, как показано ниже,

let mockUD = MockUserDefaults()
mockUD.set("avengers", forKey: "favs")

myviewController.userDefaults = mockUD

Теперь вы получите объект avengers.

2) Поскольку вопрос обновляется, вот исправление для удержания объекта mockDefaults,

struct AssociatedMock {
    static var key: UInt8 = 0
}

extension Mockable {

    private (set) var _mockDefaults: MockUserDefaults? {
        get {
            guard let value = objc_getAssociatedObject(self, &AssociatedMock.key) as? MockUserDefaults else {
                return nil
            }
            return value
        }
        set(newValue) {
            objc_setAssociatedObject(self, &AssociatedMock.key, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
        }
    }

    var userDefaults : UserDefaults {
        if (NSClassFromString("XCTest") != nil) {
            if self._mockDefaults == nil {
                self._mockDefaults = MockUserDefaults()
            }
            return self._mockDefaults!
        }
        return UserDefaults.standard
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...