Макет объекта CLBeacon в Swift

Я искал в Интернете способ макетировать объект CLBeacon, чтобы протестировать один из моих классов. Все, что я могу найти, связано с COMockito, который совместим только с Objective-c.

Все, что мне нужно, это уметь создавать фиктивный CLBeacon и устанавливать его основные минорные значения и значения UUID. Проблема в том, что эти параметры доступны только для чтения.

Любая идея о том, что я мог бы сделать, чтобы иметь фиктивный CLBeacon с параметрами, которые я установил?

1 ответ

Решение

Я не уверен, почему я всегда забываю о NSCoding, но вы можете лечить объекты CLBeacon, используя синтаксис KVO. Я наконец получил модульное тестирование, работающее с CLBeacon, вот так:

    let mockUUID = NSUUID(UUIDString: uuidString)
    let testBeacon = CLBeacon()
    testBeacon.setValue(testMajor, forKey: "major")
    testBeacon.setValue(testMinor, forKey: "minor")
    testBeacon.setValue(mockUUID, forKey: "proximityUUID")
    testBeacon.setValue(CLProximity.Far.rawValue, forKey: "proximity")

Наверное, опоздал на вечеринку. Публикуйте его на случай, если кто-то столкнется с той же проблемой.

К сожалению, по крайней мере в iOS13 на момент написания все свойства CLBeacon экранированы внутри свойства _internal NSObject, которое, в свою очередь, содержит относительное значение.

В результате вы не можете использовать простой подход "значение / ключ". Также открытый общедоступный заголовок для класса CLBeacon не предоставляет относительный метод для инициализации с произвольным значением внутреннего объекта.

В этом суть создания класса FakeBeacon Obj-C, который повторно включает требуемый метод инициализации, разрешая такой вызов также из Swift, следующим образом:

var beacon = FakeBeacon(fakeWithUUID: UUID(uuidString: uuid)!,
    major: 1,
    minor: 100,
    proximity: 2,
    accuracy: 1,
    rssi: 0,
    timestamp: Date().timeIntervalSinceReferenceDate)

Очевидно, что не стоит включать такой код в производственный IPA, иначе отказ Apple неизбежен.

Другие вопросы по тегам