2016-09-30 10 views
7

समस्या यह है कि ऑब्जेक्ट काफी जटिल है (अच्छी तरह से किसी भी दृढ़ता से टाइप की गई भाषा में) टाइपस्क्रिप्ट में मॉकिंग मुश्किल हो सकती है। उदाहरण के लिए आप आमतौर पर कोड संकलन करने के लिए कुछ अतिरिक्त सामानों का नकल करेंगे और सी # में, आप ऑटोफिक्चर या इसी तरह का उपयोग कर सकते हैं। दूसरी तरफ जावास्क्रिप्ट गतिशील भाषा है और परीक्षण के लिए आवश्यक वस्तु के केवल उस हिस्से का नकल करना संभव है।टाइपस्क्रिप्ट यूनिट परीक्षणों में मॉकिंग

तो टाइपस्क्रिप्ट यूनिट परीक्षण में मैं any प्रकार का उपयोग करके अपनी निर्भरता घोषित कर सकता हूं और इस प्रकार आसानी से इसका मज़ाक उड़ा सकता हूं। क्या आप इस तरह के दृष्टिकोण की कोई कमी देखते हैं?

let userServiceMock: MyApp.Services.UserService = { 
    // lots of thing to mock 
} 

बनाम

let userServiceMock: any = { 
    user: { 
     setting: { 
      showAvatar: true 
     } 
    } 
} 

उत्तर

10

टाइपप्रति में इकाई परीक्षण के साथ मेरा अनुभव निश्चित रूप से पता चलता है कि यह सब नकली वस्तु टाइप किया रखने के लिए लायक है। जब आप अपने मोजे को any के प्रकार से छोड़ देते हैं तो यह नाम के दौरान समस्याग्रस्त हो जाता है। आईडीई सही ढंग से नहीं खोजेगा user या settings परम की कौन सी घटनाओं को बदला जाना चाहिए। बेशक एक पूर्ण इंटरफ़ेस के साथ मैन्युअल रूप से मॉक ऑब्जेक्ट लिखना वास्तव में श्रमिक है। ts-mockito (Java mockito से प्रेरित) और typemoq (C# Moq से प्रेरित):

सौभाग्य से वहाँ टाइपप्रति प्रकार सुरक्षित नकली वस्तुओं बनाने की अनुमति देता है कि के लिए दो उपकरण हैं।

+2

मैं दो पुस्तकालयों की तुलना एक लेख लिखा था: https://medium.com/@michal.m.stocki/when-it-comes-to-mocking-in-typescript-be8531d39327 – Terite

+0

मैं लिखा है मेरा स्वयं का टूल जो इस समस्या को संभालता है, और मुझे इस पर कुछ प्रतिक्रिया पसंद आएगी: https://medium.com/default-to-open/unit-testing-with-angular-and-ineeda-76746a0c8f58 – phenomnomnominal

1

जैसा कि @Terite any द्वारा इंगित किया गया है कि मॉक्स पर टाइप खराब विकल्प है क्योंकि नकली और उसके वास्तविक प्रकार/कार्यान्वयन के बीच कोई संबंध नहीं होगा। तो बेहतर समाधान आंशिक रूप से मज़ाक उड़ाया वस्तु कास्टिंग किया जा सकता है प्रकार का मजाक उड़ाता है करने के लिए:

export interface UserService { 
    getUser: (id: number) => User; 
    saveUser: (user: User) => void; 
    // ... number of other methods/fields 
} 

.......

let userServiceMock: UserService = <UserService> { 
    saveUser(user: User) { console.log("save user"); } 
} 
spyOn(userServiceMock, 'getUser').andReturn(new User()); 
expect(userServiceMock.getUser).toHaveBeenCalledWith(expectedUserId); 

यह भी लायक उल्लेख नहीं है कि टाइपप्रति अनुमति नहीं दी जाएगी किसी भी वस्तु कास्ट करने के लिए कि अतिरिक्त सदस्य हैं (सुपरसेट या व्युत्पन्न प्रकार)। इसका मतलब है कि आपका आंशिक नकल वास्तव में UserService पर मूल प्रकार का है और इसे सुरक्षित रूप से कास्ट किया जा सकता है। जैसे

// Error: Neither type '...' nor 'UserService' is assignable to the other. 
let userServiceMock: UserService = <UserService> { 
    saveUser(user: User) { console.log("save user"); }, 
    extraFunc:() => { } // not available in UserService 
} 
+0

क्यों, है आंशिक रूप से मजाकिया वस्तुओं के लिए आपके लिए यह महत्वपूर्ण है? एक ही सेवा में सार्वजनिक क्षेत्रों और सार्वजनिक तरीकों के बारे में बुरा विचार है। विधि 'setAvatarVisibility (दृश्यमान: बूलियन)' को परिभाषित करना बेहतर हो सकता है और 'उपयोगकर्ता' फ़ील्ड को निजी रखें। फिर आप मैन्युअल जासूसी से बचेंगे। ध्यान दें कि 'spyOn (userServiceMock,' saveUser ') में;' विधि का स्ट्रिंग नाम आईडीई द्वारा स्वचालित रूप से दोबारा नहीं किया जाएगा। – Terite

+0

फिर भी एक और, बेहतर समाधान 'उपयोगकर्ता' ऑब्जेक्ट को सेवा के बाहर रखना होगा। अगर हम सेवाओं को स्टेटलेस रखते हैं तो कोड परीक्षण करना आसान है। उपयोगकर्ता को 'विधि' सेवा प्राप्त करने के बारे में आप क्या सोचते हैं: 'saveUser (उपयोगकर्ता: उपयोगकर्ता): शून्य; '? – Terite

+0

मैंने इस कोड का इस्तेमाल केवल उदाहरण के रूप में किया था, शायद सबसे अच्छा नहीं, लेकिन ऐसा कुछ नहीं है जिसे मैं नकल करने की कोशिश कर रहा था। मैं सिर्फ एक सामान्य समाधान की तलाश में हूं। और हाँ आपके उदाहरण निश्चित रूप से बेहतर हैं, सलाह के लिए धन्यवाद। –

संबंधित मुद्दे