简体   繁体   English

如何模拟EKEventStore

[英]How to mock EKEventStore

I have a simple function for requesting access for adding events in the Calendar. 我有一个简单的函数来请求访问以在日历中添加事件。

typealias BoolCallback = (Bool) -> ()

class SimpleCalendar {

    let store: EKEventStore

    init(store: EKEventStore = EKEventStore()) {
        self.store = store
    }

    /// Request access to EventKit API for Calendar intergration
    ///
    /// - Parameter callback: returns if access was recived or denied
    func requestAccess(callback: @escaping BoolCallback) {

        let status = EKEventStore.authorizationStatus(for: .event)

        switch status {
        case .authorized:
            callback(true)
            //        case .notDetermined: //should ask for access
        //        case .denied, .restricted: //should open a ask permission view
        default:
            store.requestAccess(to: .event) { accessGranted, _ in

                DispatchQueue.main.async {
                    callback(accessGranted)
                }
            }
        }


    }
}

Is there a way to mock EKEventStore for getting the status? 有没有办法模拟EKEventStore获取状态?

I also have a simple function that checks if a calendar exists. 我还有一个简单的函数来检查日历是否存在。

func doesCalendarExist(name: String) -> Bool {
    let calendars = store.calendars(for: .event)

    if calendars.contains(where: { $0.title == name }) {
        return true
    }

    return false
}

Is there a way to mock the store objects for getting store.calendars 有没有办法模拟商店对象获取store.calendars

Thanks 谢谢


I switched 我换了

let status = EKEventStore.authorizationStatus(for: .event)

to

let status = type(of: store).authorizationStatus(for: .event)

I think you can use DI here. 我想你可以在这里使用DI。 Instead of put responsibility of creating store var inside of SimpleCalendar you can create constructor for it with parameter store: EKEventStore and pass it there: 您可以使用参数存储:EKEventStore为其创建构造函数,而不是在SimpleCalendar中创建存储var的责任,并将其传递给:

init(store: EKEventStore = EKEventStore()) {/*code*/}

This way, you can pass your own mock object. 这样,您就可以传递自己的模拟对象。

What is the issue with overriding class method? 覆盖类方法有什么问题? I can't check it right now, but suppose it's possible. 我现在无法检查它,但假设它是可能的。

Any way, other option is for mocking you can create protocol with all the methods you're using - EventStoreProtocol . 无论如何,其他选项是用于模拟,您可以使用您正在使用的所有方法创建协议 - EventStoreProtocol These methods must be in EKEventStore I think, so you can easily adopt it using extension: 我认为这些方法必须在EKEventStore中 ,因此您可以使用扩展名轻松采用它:

extension EKEventStore: EventStoreProtocol {}

Then instead of passing EKEventStore to constructor, pass there EventStoreProtocol . 然后,不是将EKEventStore传递给构造函数,而是传递EventStoreProtocol

Your mock object will be not subclass, but just class confirming to that protocol, implementing all required methods 您的模拟对象将不是子类,而只是确认该协议的类,实现所有必需的方法

For class method, instead of EKEventStore.authorizationStatus use type(of: store).authorizationStatus 对于类方法,使用type(of:store) .authorizationStatus而不是EKEventStore.authorizationStatus

The only thing I can think of regarding your problem is the next: 关于你的问题,我唯一能想到的就是下一个:

extension EKEventStore {
   func eventAuthorizationStatus() -> EKAuthorizationStatus {
      return EKEventStore.authorizationStatus(for: .event)
   }
}

Then override this method in subclass. 然后在子类中重写此方法。 Because EKEventStore is NSObject , it should work (but I'm not sure). 因为EKEventStoreNSObject ,它应该工作(但我不确定)。 This way instead of using type(of: store).authorizationStatus you can call this method. 这样,您可以调用此方法,而不是使用type(of:store).authorizationStatus

But the question - do you really need this? 但问题是 - 你真的需要这个吗? Can't you just left it as is? 你不能把它原样留下吗? If no, check this approach and tell me, if it works 如果不是,请检查此方法并告诉我它是否有效

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM