I'm developing a calendar app where I'm struggling to create tests for the functions that utilize the calendars on the users device. The
calendar: EKCalendar
variable is taken from the users event store so when the unit tests run on XCode's emulator they fail as the calendar doesn't exist. Using my personal device works but then the tests would fail on our build server.
What are good approaches to test a function/computed property that uses the User's calendar/eventstore?
///Return the user's name. If this hasn't been saved extract their name from their Enterprise calendar and save it.
static var name: String? {
if let savedName = defaults.string(forKey: "name") {
return savedName
}
// calendar is a specific EKCalendar members of my company will have.
guard let calendar = MeetingsFetcher().getUserEnterpriseCalendars().first,
let parsedName = calendar.title.firstMatch(from: Regex.organizerNameFromEKCalendar) else {
return nil
}
defaults.set(parsedName, forKey: "name")
return parsedName
}
func getEnterpriseCalendars() -> [EKCalendar]{
guard EKEventStore.authorizationStatus(for: .event) == .authorized else { return [EKCalendar]() }
for calendar in MeetingsFetcher.eventStoreClass.calendars(for: .event) {
if calendar.source.title.range(of: "IBM") != nil{
return [calendar]
}
}
return [EKCalendar]()
}
Ignore that it is returning an array, I'm not really sure why it does that :p
So let clarify what you actually have to test in your function.
MeetingsFetcher().getUserEnterpriseCalendar()
calendar.title.firstMatch(from: Regex.organizerNameFromEKCalendar)
My assumption is your want to test both of them. But as the issue you mention I think it's impossible to actually test if your getUserEnterpriseCalendar
function is actually work correctly on simulator because it won't return anything anywhere (except you create the script on your build server to let simulator subscribe or add your calendar on it)
However I can suggest you to mock getUserEnterpriseCalendar
function and make an assumption in your unit test that getUserEnterpriseCalendar
will return correct value in any environment. You may need to chnage your computed property to function and pass MeetingFetcher as parameter for this.
// function modification
static func name(from meetingFetcher: MeetingFetcher) -> String {
if let savedName = defaults.string(forKey: "name") {
return savedName
}
// calendar is a specific EKCalendar members of my company will have.
guard let calendar = meetingFetcher.getUserEnterpriseCalendar().first,
let parsedName = calendar.title.firstMatch(from: Regex.organizerNameFromEKCalendar) else {
return nil
}
defaults.set(parsedName, forKey: "name")
return parsedName
}
// In testing code.
func testOrganizationCalendar() {
class MockedMeetingFetcher: MeetingFetcher {
override func getUserEnterpriseCalendars() -> [EKCalendar] {
let calendar1 = EKCalendar()
calendar1.title = "ExpectedToMatchRegexTitle"
return [calendar1]
}
}
XCTestAssertEqual(YourClass.name(from: MockedMeetingFetcher()), "Hure!!!")
}
I hope it may help even just give you some ideas.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With