2015-12-03 7 views
5

, मैं कभी कभी परीक्षण है कि सही ढंग से बात वे परखने के लिए बनाई परीक्षण करने के लिए कॉन्फ़िगर नहीं किया गया लगता है AutoFixture.AutoMoq पैकेज के साथ AutoFixture का उपयोग करना, लेकिन समस्या यह है डिफ़ॉल्ट (ढीला) नकली व्यवहार के कारण की खोज की कभी नहीं किया गया था:मैं ऑटोमोक कस्टमाइज़ेशन को सख्त मॉकबैवियर का उपयोग कैसे कर सकता हूं?

public interface IService 
{ 
    bool IsSomethingTrue(int id); 
} 

void Main() 
{ 
    var fixture = new Fixture() 
     .Customize(new AutoMoqCustomization()); 
    var service = fixture.Freeze<Mock<IService>>(); 
    Console.WriteLine(service.Object.IsSomethingTrue(1)); // false 
} 

मैं सख्त व्यवहार के साथ मोक्स बनाना चाहता हूं, इसलिए हमें उन तरीकों के लिए Setup() पर कॉल करने के लिए मजबूर होना पड़ता है। मैं इस तरह प्रत्येक व्यक्ति नकली के लिए ऐसा कर सकते हैं:

fixture.Customize<Mock<IService>>(c => c.FromFactory(() => new Mock<IService>(MockBehavior.Strict))); 

लेकिन AutoMoqCustomization() और विभिन्न ISpecimenBuilder और अन्य कार्यान्वयन के लिए स्रोत कोड के माध्यम से कंघी के बाद, मैं बहुत सबसे अच्छा तरीका करने के लिए के रूप में खो रहा हूँ बस सभी बनाने के लिए सख्त व्यवहार के साथ मोक्स शुरू हो जाते हैं। ढांचा बहुत लचीला और एक्स्टेंसिबल प्रतीत होता है, इसलिए मुझे यकीन है कि ऐसा करने का एक आसान तरीका है - मैं बस यह नहीं समझ सकता कि कैसे।

उत्तर

3

कोई आसान अंतर्निहित सुविधा नहीं है जो आपको ऐसा कुछ करने में सक्षम करेगी, लेकिन यह नहीं होना चाहिए करना मुश्किल है।

अनिवार्य रूप से, आपको MockConstructorQuery को बदलने की आवश्यकता होगी ताकि यह उस निर्माता को आमंत्रित करे जो MockBehavior मान लेता है, और MockBehavior.Strict में पास हो जाता है।

अब, आप नहीं परिवर्तन कर सकते हैं MockConstructorQuery में है कि व्यवहार, लेकिन उस वर्ग कोड का केवल कुछ 9-10 लाइनों है, तो आप एक नया वर्ग है कि एक प्रारंभिक रूप MockConstructorQuery का उपयोग करके IMethodQuery लागू करता है बनाने के लिए सक्षम होना चाहिए बिंदु।

इसी तरह, आप भी एकमात्र अपवाद है कि यह बजाय सख्त नकली विन्यास MockConstructorQuery साथ अपने कस्टम IMethodQuery का उपयोग करता है के साथ, एक कस्टम ICustomization कि लगभग ठीक AutoMoqCustomization के रूप में ही होता है बनाने की आवश्यकता होगी। कोड की एक और 7 लाइनें आपको लिखने की आवश्यकता होगी।

मेरे अनुभव में, सख्त मैक्स का उपयोग करके एक बुरा विचार है। यह आपके परीक्षणों को भंग कर देगा, और आप 'टूटा' परीक्षणों में बहुत समय बर्बाद कर देंगे। मैं केवल यह सिफारिश कर सकता हूं कि आप ऐसा नहीं करते हैं, लेकिन अब मैंने आपको चेतावनी दी है; यह तुम्हारा पैर है

+0

प्रतिक्रिया के लिए धन्यवाद। मैं देखूंगा कि मैं इसे काम कर सकता हूं या नहीं। सख्त मोजे के बारे में: यदि मॉक्स वास्तव में "झुंड" थे, तो मुझे लगता है कि आपका बिंदु मान्य है। दुर्भाग्य से, मेरे ज्यादातर मोक्स वास्तव में * स्टब्स * के उद्देश्य को पूरा करते हैं, जिन्हें एक मूल्य वापस करने की उम्मीद है। यदि एसयूटी स्टब से लौटाए गए डेटा पर निर्भर करता है, और मैंने स्टब सेट नहीं किया है, तो सबसे अच्छे मामले में परीक्षण विफल हो जाएगा, और सबसे बुरे मामले में परीक्षण गलत कारण के लिए पास होगा। एनआरई कहां से आ रहा है, इसे कम करने के बजाए, मुझे किसी भी मामले में, तुरंत कोड की रेखा को देखने के लिए, जिसे स्टब को कॉन्फ़िगर करने की आवश्यकता है, को पसंद करना होगा। – StriplingWarrior

+0

@StriplingWarrior http://blog.ploeh.dk/2013/10/23/mocks-for-commands-stubs-for-queries –

+0

मुझे लगता है कि लेख का उदाहरण बहुत बढ़िया है: उपयोगकर्ता वस्तु बनाने और वापस करने के लिए CQS को तोड़ना जिसमें GetUser विधि को प्रदान की गई आईडी भी नहीं है।वे ऐसे बदलाव नहीं हैं जिन्हें मैं आम तौर पर तरीकों से बना रहा हूं। जो परिवर्तन मैं नियमित रूप से देखता हूं उन्हें वैसे भी यूनिट परीक्षण में बदलाव की आवश्यकता होती है, भले ही वे उस आलेख में अंतिम सही उदाहरण की तरह लिखे जाएं। जब ऐसा होता है, तो मुझे लगता है कि सख्त मोक्स 'असफल-तेज व्यवहार बहुत समय बचाता है और - अधिक महत्वपूर्ण बात यह सुनिश्चित करने में सहायता करता है कि मेरे यूनिट परीक्षण परीक्षण कर रहे हैं जो वे परीक्षण करने का दावा करते हैं। – StriplingWarrior

0

रुचि रखने वालों के लिए, नीचे आप @ MarkSeemann का उत्तर कोड में अनुवाद कर सकते हैं। मुझे पूरा यकीन है कि इसमें सभी उपयोग मामलों को शामिल नहीं किया गया है और इसका भारी परीक्षण नहीं किया गया था। लेकिन यह एक अच्छा प्रारंभिक बिंदु होना चाहिए।

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Reflection; 
using Moq; 
using Ploeh.AutoFixture; 
using Ploeh.AutoFixture.AutoMoq; 
using Ploeh.AutoFixture.Kernel; 

namespace ConsoleApplication1 
{ 
    public class StrictAutoMoqCustomization : ICustomization 
    { 
     public StrictAutoMoqCustomization() : this(new MockRelay()) { } 

     public StrictAutoMoqCustomization(ISpecimenBuilder relay) 
     { 
      // TODO Null check params 
      Relay = relay; 
     } 

     public ISpecimenBuilder Relay { get; } 

     public void Customize(IFixture fixture) 
     { 
      // TODO Null check params 
      fixture.Customizations.Add(new MockPostprocessor(new MethodInvoker(new StrictMockConstructorQuery()))); 
      fixture.ResidueCollectors.Add(Relay); 
     } 
    } 

    public class StrictMockConstructorMethod : IMethod 
    { 
     private readonly ConstructorInfo ctor; 
     private readonly ParameterInfo[] paramInfos; 

     public StrictMockConstructorMethod(ConstructorInfo ctor, ParameterInfo[] paramInfos) 
     { 
      // TODO Null check params 
      this.ctor = ctor; 
      this.paramInfos = paramInfos; 
     } 

     public IEnumerable<ParameterInfo> Parameters => paramInfos; 

     public object Invoke(IEnumerable<object> parameters) => ctor.Invoke(parameters?.ToArray() ?? new object[] { }); 
    } 

    public class StrictMockConstructorQuery : IMethodQuery 
    { 
     public IEnumerable<IMethod> SelectMethods(Type type) 
     { 
      if (!IsMock(type)) 
      { 
       return Enumerable.Empty<IMethod>(); 
      } 

      if (!GetMockedType(type).IsInterface && !IsDelegate(type)) 
      { 
       return Enumerable.Empty<IMethod>(); 
      } 

      var ctor = type.GetConstructor(new[] { typeof(MockBehavior) }); 

      return new IMethod[] 
      { 
       new StrictMockConstructorMethod(ctor, ctor.GetParameters()) 
      }; 
     } 

     private static bool IsMock(Type type) 
     { 
      return type != null && type.IsGenericType && typeof(Mock<>).IsAssignableFrom(type.GetGenericTypeDefinition()) && !GetMockedType(type).IsGenericParameter; 
     } 

     private static Type GetMockedType(Type type) 
     { 
      return type.GetGenericArguments().Single(); 
     } 

     internal static bool IsDelegate(Type type) 
     { 
      return typeof(MulticastDelegate).IsAssignableFrom(type.BaseType); 
     } 
    } 
} 

प्रयोग

var fixture = new Fixture().Customize(new StrictAutoMoqCustomization()); 
संबंधित मुद्दे