Moq

2010-07-19 19 views
25

का उपयोग कर एक आंतरिक कन्स्ट्रक्टर के साथ एक प्रकार का मज़ाक उड़ाते हुए मैं माइक्रोसॉफ्ट सिंक फ्रेमवर्क से कक्षा को नकल करने की कोशिश कर रहा हूं। इसमें केवल एक आंतरिक कन्स्ट्रक्टर है। मैं निम्नलिखित का प्रयास करते हैं:Moq

var fullEnumerationContextMock = new Mock<FullEnumerationContext>(); 

मैं इस त्रुटि मिलती है:

System.NotSupportedException: Parent does not have a default constructor. The default constructor must be explicitly defined.

यह स्टैक ट्रेस है:

System.Reflection.Emit.TypeBuilder.DefineDefaultConstructorNoLock(MethodAttributes attributes) System.Reflection.Emit.TypeBuilder.DefineDefaultConstructor(MethodAttributes attributes) System.Reflection.Emit.TypeBuilder.CreateTypeNoLock() System.Reflection.Emit.TypeBuilder.CreateType() Castle.DynamicProxy.Generators.Emitters.AbstractTypeEmitter.BuildType() Castle.DynamicProxy.Generators.ClassProxyGenerator.GenerateCode(Type[] interfaces, ProxyGenerationOptions options) Castle.DynamicProxy.DefaultProxyBuilder.CreateClassProxy(Type classToProxy, Type[] additionalInterfacesToProxy, ProxyGenerationOptions options) Castle.DynamicProxy.ProxyGenerator.CreateClassProxyType(Type classToProxy, Type[] additionalInterfacesToProxy, ProxyGenerationOptions options) Castle.DynamicProxy.ProxyGenerator.CreateClassProxy(Type classToProxy, Type[] additionalInterfacesToProxy, ProxyGenerationOptions options, Object[] constructorArguments, IInterceptor[] interceptors) Castle.DynamicProxy.ProxyGenerator.CreateClassProxy(Type classToProxy, Type[] additionalInterfacesToProxy, ProxyGenerationOptions options, IInterceptor[] interceptors) Castle.DynamicProxy.ProxyGenerator.CreateClassProxy(Type classToProxy, Type[] additionalInterfacesToProxy, IInterceptor[] interceptors) Moq.Mock 1.<InitializeInstance>b__0() Moq.PexProtector.Invoke(Action action) Moq.Mock 1.InitializeInstance()

मैं इस दौर कैसे काम कर सकते हैं?

+3

इस सवाल के लिए धन्यवाद! यह केवल अस्तित्व में मेरी मदद की। मैं अपने कोड पर, निर्माता को सार्वजनिक बनाने में सक्षम था। दुर्भाग्यवश यह आपके मामले में आपकी सहायता नहीं कर सकता है, लेकिन आपने अभी भी +1 – Marcel

उत्तर

17

आप ऐसे प्रकार का नकल नहीं कर सकते हैं जिसमें सार्वजनिक निर्माता नहीं है क्योंकि Moq उस प्रकार की किसी ऑब्जेक्ट को तुरंत चालू नहीं कर पाएगा। क्या आप परीक्षण करने के लिए कोशिश कर रहे हैं पर निर्भर करता है, तो आप कुछ ही विकल्प हैं:

  1. एक कारखाने वस्तु या FullEnumerationContext के उदाहरण प्राप्त करने के शायद आप उपयोग कर सकते हैं (क्षमा करें, मैं से परिचित नहीं हूँ के किसी अन्य तरीके से होती है, तो सिंक फ्रेमवर्क)
  2. आप एक पूर्ण एनीमेशन कॉन्टैक्ट को तुरंत चालू करने के लिए निजी प्रतिबिंब का उपयोग कर सकते हैं, लेकिन फिर आप इसके तरीकों पर नकल करने में सक्षम नहीं होंगे।
  3. आप एक इंटरफ़ेस और/या रैपर ऑब्जेक्ट पेश कर सकते हैं जो मजाक कर रहा है कि परीक्षण के तहत कोड आ सकता है। रनटाइम कार्यान्वयन वास्तविक FullEnumerationContext को प्रस्तुत करेगा, जबकि आपका परीक्षण-समय कार्यान्वयन आपको जो भी कार्रवाई करेगा, करेगा।
+3

वास्तव में आप एक आंतरिक कन्स्ट्रक्टर के साथ कक्षा के लिए नकली तुरंत कर सकते हैं। Https://code.google में "उन्नत सुविधाएं" में बताए गए अनुसार, आपको लक्षित असेंबली पर लागू उचित आंतरिक दृश्यों की आवश्यकता है।com/p/moq/wiki/QuickStart – kzu

+11

@kzu यह किसी तृतीय पक्ष लाइब्रेरी पर काम नहीं करेगा क्योंकि आप स्वयं लाइब्रेरी का निर्माण नहीं कर रहे हैं। – DBueno

3

मैं वास्तव में मोक पर एक विशेषज्ञ नहीं हूं, लेकिन मुझे लगता है कि आपको कन्स्ट्रक्टर के लिए तर्क निर्दिष्ट करने की आवश्यकता है। राइनो मोक्स में आप उन्हें इस तरह निर्दिष्ट करेंगे:

var fullEnumerationContextMock = new Mock<FullEnumerationContext>(arg1, arg2); 

यह शायद मोक में समान है।

+1

की मदद की है क्या कोई यह पुष्टि कर सकता है कि यह मक के साथ संभव है या नहीं? मैं Moq 3.1 – tjrobinson

+0

नंबर का उपयोग कर रहा हूं। ऐसा नहीं है। कैसल क्लास-बाय-टाइप सृजन के लिए डिफ़ॉल्ट कन्स्ट्रक्टर का उपयोग करता है। कम से कम यही मैं यहां पढ़ता हूं [गिटहब पर] (https://github.com/castleproject/Core/blob/c06adf27bf7a0dfe94529a2563aca94bdedd1cb0/src/Castle.Core/DynamicProxy/Generators/Emitters/AbstractTypeEmitter.cs#L323) – durilka

+3

यह केवल यदि आप सार्वजनिक गैर-डिफ़ॉल्ट कन्स्ट्रक्टर के साथ कुछ मकिंग कर रहे हैं तो सच है। एक आंतरिक कन्स्ट्रक्टर (डिफ़ॉल्ट या अन्यथा) के लिए आप भाग्य से बाहर हैं। – RJFalconer

1

मैं एक इंटरफेस (IFullEnumerationContext) बना लिया है marcind से जवाब जो मैं नकली और फिर मैं विधि मैं परीक्षण करने के लिए कोशिश कर रहा हूँ, एक कि FullEnumerationContext लेता के दो भार के मिल गया है के आधार पर और दूसरा वह लेता है IFullEnumerationContext। यह बहुत अच्छा नहीं लगता है, लेकिन यह काम करता है। किसी भी बेहतर सुझाव या सुधार का स्वागत किया जाएगा।

public override void EnumerateItems(FullEnumerationContext context) 
{ 
    List<ItemFieldDictionary> listItemFieldDictionary = EnumerateItemsCommon(); 
    context.ReportItems(listItemFieldDictionary); 
} 

public void EnumerateItems(IFullEnumerationContext context) 
{ 
    List<ItemFieldDictionary> listItemFieldDictionary = EnumerateItemsCommon(); 
    context.ReportItems(listItemFieldDictionary); 
} 
+0

मुझे लगता है कि यह बेहतर होगा अगर ओवरलोड जो 'FullEnumerationContext' लेता है, संदर्भ पूर्णता को' FullEnumerationContextWrapper' में लपेटता है और उसके बाद उस ओवरलोड में पारित होता है जो 'IFullEnumerationContext' स्वीकार करता है। इस तरह से इन तरीकों में से केवल एक ही महत्वपूर्ण कोड होगा। दूसरा एक एक पंक्ति बयान होगा जिसमें इसके साथ जुड़े यूनिट परीक्षण की आवश्यकता नहीं है। – marcind

0

वास्तव में आप कर सकते हैं। अपने AssemblyInfo.cs फ़ाइल और अंत में निम्नलिखित पंक्ति जोड़ खोलें,

[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]