2016-11-29 9 views
6

मेरे ऐप में मैं यह कहना चाहता हूं कि नोटिफिकेशन सही प्रारूप में जोड़े गए हैं। मैं आमतौर पर निर्भरता इंजेक्शन के साथ ऐसा करता हूं, लेकिन मैं नए UNUserNotificationCenter एपीआई का परीक्षण करने के तरीके के बारे में नहीं सोच सकता। मैं नकली का दृष्टांत नहीं कर सकतेयूनिट परीक्षण आईओएस 10 नोटिफिकेशन

import Foundation 
import UserNotifications 

class NotificationCenterMock: UNUserNotificationCenter { 
    var request: UNNotificationRequest? = nil 
    override func add(_ request: UNNotificationRequest, withCompletionHandler completionHandler: ((Error?) -> Void)? = nil) { 
     self.request = request 
    } 
} 

हालांकि, UNUserNotificationCenter कोई सुलभ initializers है:

मैं एक नकली वस्तु जो अधिसूचना अनुरोध पर कब्जा होगा बनाने के लिए शुरू कर दिया।

मुझे यह भी सुनिश्चित नहीं है कि मैं अधिसूचना अनुरोध जोड़कर और वर्तमान अधिसूचनाएं लाकर परीक्षण कर सकता हूं, क्योंकि परीक्षणों को सिम्युलेटर पर अनुमति का अनुरोध करने की आवश्यकता होगी जो परीक्षणों को रोक देगा। वर्तमान में मैंने अधिसूचना तर्क को एक रैपर में दोहराया है, इसलिए मैं कम से कम अपने आवेदन के दौरान नकल कर सकता हूं और मैन्युअल रूप से परीक्षण कर सकता हूं।

क्या मेरे पास मैन्युअल परीक्षण से बेहतर विकल्प हैं?

उत्तर

7

आप जिस विधियों का उपयोग कर रहे हैं, उनके लिए प्रोटोकॉल बना सकते हैं, और इसके अनुरूप यूएनयूसर नॉटिफिकेशन सेंटर पर विस्तार कर सकते हैं। यह प्रोटोकॉल मूल विधि UNUserNotificationCenter कार्यान्वयन और आपके विधि कार्यान्वयन को प्रतिस्थापित करने के लिए आपके नकली ऑब्जेक्ट के बीच "पुल" के रूप में कार्य करेगा।

यहाँ एक उदाहरण कोड मैं एक खेल के मैदान में लिखा है, और ठीक काम करता है:

/* UNUserNotificationCenterProtocol.swift */ 

// This protocol allows you to use UNUserNotificationCenter, and replace the implementation of its 
// methods in you test classes. 
protocol UNUserNotificationCenterProtocol: class { 
    // Declare only the methods that you'll be using. 
    func add(_ request: UNNotificationRequest, 
      withCompletionHandler completionHandler: ((Error?) -> Void)?) 
} 

// The mock class that you'll be using for your test classes. Replace the method contents with your mock 
// objects. 
class MockNotificationCenter: UNUserNotificationCenterProtocol { 
    func add(_ request: UNNotificationRequest, 
      withCompletionHandler completionHandler: ((Error?) -> Void)?) { 
    // Do anything you want here for your tests 
    print("Mock center log") 
    completionHandler?(nil) 
    } 
} 

// Must extend UNUserNotificationCenter to conform to this protocol in order to use it in your class. 
extension UNUserNotificationCenter: UNUserNotificationCenterProtocol { 
// I'm only adding this implementation to show a log message in this example. In order to use the original implementation, don't add it here. 
    func add(_ request: UNNotificationRequest, withCompletionHandler completionHandler: ((Error?) -> Void)?) { 
    print("Notification center log") 
    completionHandler?(nil) 
    } 
} 

/* ExampleClass.swift */ 

class ExampleClass { 

    // Even though the type is UNUserNotificationCenterProtocol, it will take UNUserNotificationCenter type 
    // because of the extension above. 
    var notificationCenter: UNUserNotificationCenterProtocol = UNUserNotificationCenter.current() 

    func doSomething() { 
    // Create a request. 
    let content = UNNotificationContent() 
    let request = UNNotificationRequest(identifier: "Request", 
              content: content, 
              trigger: nil) 
    notificationCenter.add(request) { (error: Error?) in 
     // completion handler code 
    } 
    } 
} 

let exampleClass = ExampleClass() 
exampleClass.doSomething() // This should log "Notification center log" 

/* TestClass.Swift (unit test class) */ 

class TestClass { 

    // Create your mock class. 
    var notificationCenter: UNUserNotificationCenterProtocol = MockNotificationCenter() 

    func doSomething() { 
    // Create a mock Request. 
    let fakeContent = UNNotificationContent() 
    let mockRquest = UNNotificationRequest(identifier: "mock", 
              content: fakeContent, 
              trigger: nil) 
    notificationCenter.add(mockRquest) { (error: Error?) in 
     // completion handler code 
    } 
    } 
} 

let testClass = TestClass() 
testClass.doSomething() // This should log "Mock center log" 

ध्यान रखें कि हर बार जब आप एक नई पद्धति का उपयोग करें, आप प्रोटोकॉल में जोड़ने के लिए होगा, या संकलक शिकायत करेंगे।

आशा है कि इससे मदद मिलती है!

+0

एक स्मार्ट समाधान की तरह लगता है, धन्यवाद! – squarefrog

+0

यह एक महान प्रतिक्रिया है। क्या आपको लगता है कि मॉक 'func getNotificationSettings (completHandler: @escaping (UNNotificationSettings) -> Swift.Void) के लिए एक समान दृष्टिकोण का पालन करना संभव है? मुझे लौटा 'UNNotificationSettings' ऑब्जेक्ट का मज़ाक उड़ाते हुए परेशानी हो रही है क्योंकि इसे तत्काल नहीं किया जा सकता है। – JimmyB