How to test Contacts Framework

267 views Asked by At

hi i want to test CNContacts Store since this is my first time doing test, i don't have any idea how to conduct a unit test. This the code i want to test.

 private func fetchContacts() {
        var contacts: [Contact] = []
        let keys: [CNKeyDescriptor] = [CNContactFormatter.descriptorForRequiredKeys(for: .fullName),
                                       CNContactPhoneNumbersKey as CNKeyDescriptor]
        let request = CNContactFetchRequest(keysToFetch: keys)
        
        
        do {
            try contactStore.enumerateContacts(with: request) {
                (contact, stop) in
                let name: String = CNContactFormatter.string(from: contact, style: .fullName) ?? contact.nickname
                contacts.append(contentsOf: contact.phoneNumbers.compactMap({ phoneNumber in
                    let phoneNumberString: String = phoneNumber.value.stringValue
                    return .init(name: name, phoneNumber: phoneNumberString)
                }))
            }
            
            allContacts = contacts
            isContactsFetched = true
            filterContacts()
        }
        catch {
            print("unable to fetch contacts")
        }
    }

I'm using sourcery to generate mock from CNContactStore this is the enumerated mock i generate using sorcery

//MARK: - enumerateContacts

    var enumerateContactsWithUsingBlockThrowableError: Error?
    var enumerateContactsWithUsingBlockCallsCount = 0
    var enumerateContactsWithUsingBlockCalled: Bool {
        return enumerateContactsWithUsingBlockCallsCount > 0
    }
    var enumerateContactsWithUsingBlockReceivedArguments: (fetchRequest: CNContactFetchRequest, block: (CNContact, UnsafeMutablePointer<ObjCBool>) -> Void)?
    var enumerateContactsWithUsingBlockReceivedInvocations: [(fetchRequest: CNContactFetchRequest, block: (CNContact, UnsafeMutablePointer<ObjCBool>) -> Void)] = []
    var enumerateContactsWithUsingBlockClosure: ((CNContactFetchRequest, @escaping (CNContact, UnsafeMutablePointer<ObjCBool>) -> Void) throws -> Void)?

    func enumerateContacts(with fetchRequest: CNContactFetchRequest, usingBlock block: @escaping (CNContact, UnsafeMutablePointer<ObjCBool>) -> Void) throws {
        if let error = enumerateContactsWithUsingBlockThrowableError {
            throw error
        }
        enumerateContactsWithUsingBlockCallsCount += 1
        enumerateContactsWithUsingBlockReceivedArguments = (fetchRequest: fetchRequest, block: block)
        enumerateContactsWithUsingBlockReceivedInvocations.append((fetchRequest: fetchRequest, block: block))
        try enumerateContactsWithUsingBlockClosure?(fetchRequest, block)
    }

what i did so far for unit test is this

it("should fetch contacts") {
                            
    let contact = CNContact()
    let stop = UnsafeMutablePointer<ObjCBool>.allocate(capacity: 1)
    stop[0] = true
                            
    // When
    viewModel.onViewDidAppear()
                            
    // Then
    mockContactStore.enumerateContactsWithUsingBlockClosure = { (_, args) in
                                args(contact, stop)
                                
                                
                                
expect(mockContactStore.enumerateContactsWithUsingBlockCallsCount).to(equal(1))
  }
}

Please help

1

There are 1 answers

0
Tomdwipo On

if you want to test this ->

let request = CNContactFetchRequest(keysToFetch: keys)

you can do like this ->

protocol CNContactFetchRequestProtocol {
    
}

extension CNContactFetchRequest: CNContactFetchRequestProtocol {
    
}

let request: CNContactFetchRequestProtocol = CNContactFetchRequest(keysToFetch: keys)

and finally you can create mock

class MockContact: CNContactFetchRequestProtocol {
}

and then you can tests like this:

let request: CNContactFetchRequestProtocol = MockContact()