2011-05-31 16 views
6

कहा जाता है मुझे Moq का उपयोग करके कुछ परेशानी होती है। निम्नलिखित इकाई परीक्षण एक अपवाद फेंकता है, भले ही विधि विधि कहा जाएगा।Moq सत्यापित विधि विफल रहता है भले ही विधि

[TestMethod] 
public void CreateFinishTest() { 
    // mock methods 
    factoryMock.Setup(f => f.LoadPlan("TestPlanDoNotUse")).Returns(testPlan).Verifiable(); 
    factoryMock.Setup(f => f.CreateFinish(It.IsAny<CreateFinishMessage>(), It.IsAny<string>())).Returns(testFinish.Id).Verifiable(); 

    try { 
     var cfm = new CreateFinishMessage() { 
      ClientId = 11, 
      MessageId = 23456, 
      CustomerId = 6, 
      FinishName = "MyFinish", 
      PlanId = "TestPlanDoNotUse" 
     }; 
     var cmd = sysCfg.Executor.CreateFinish(cfm); // calls LoadPlan with cfm.PlanId and CreateFinish with cfm and cfm.PlanId 
     sysCfg.Executor.Execute(cmd); 

     factoryMock.Verify(f => f.LoadPlan("TestPlanDoNotUse"), Times.Exactly(1)); 
     factoryMock.Verify(f => f.CreateFinish(It.IsAny<CreateFinishMessage>(), It.IsAny<string>()), Times.Exactly(1)); 
    } catch (Exception exc) { 
     Assert.Fail(exc.Message); 
    } 
} 

यह त्रुटि होती है:

Expected invocation on the mock exactly 1 times, but was 0 times: f => f.LoadPlan("TestPlanDoNotUse") 

Configured setups: 
f => f.LoadPlan("TestPlanDoNotUse"), Times.Once 

Performed invocations: 
IFactory.LoadPlan("TestPlanDoNotUse") 
Factory.CreateFinish(IndiValue.LiveMarket.IndiCore.Communication.MessagingFormat.CreateFinishMessage, "MyFinish") 

मैं कई अलग अलग सत्यापित करें-कॉल की कोशिश की है, लेकिन यह काम नहीं करेगा। और जो त्रुटि होती है वह काफी भ्रमित लगता है कि यह कहता है कि LoadPlan("TestPlanDoNotUse") कभी नहीं कहा जाता है, लेकिन यह @ प्रदर्शन किए गए आमंत्रण सूचीबद्ध है।

समस्या हल:

मैं मैं समस्या पाया लगता है, है ना एक Moq समस्या थी। sysCfg.Executor.CreateFinish(cfm) में एक नया धागा बनाया गया था और शुरू किया गया था। यह धागा समाप्त नहीं हुआ था और इसलिए factoryMock.Verify(...) विफल रहा।

मैं AutoResetEvents प्रयोग किया है:

// create AutoResetEvent triggers 
AutoResetEvent m_testTrigger1 = new AutoResetEvent(false); 

// mock methods  
factoryMock.Setup(f => f.LoadPlan(It.IsAny<string>())).Returns(testPlan).Callback(() => m_testTrigger1.Set()); 

// do something 

// wait for triggers 
bool didReturn1 = m_testTrigger1.WaitOne(timeOut); 

उत्तर

6

सत्यापन योग्य नहीं होने पर, यह महत्वपूर्ण है कि आपकी अपेक्षाओं में तर्क उन तर्कों से मेल खाते हैं जिनका उपयोग उत्पादन कोड द्वारा किया जा रहा है।

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

peek here on a small utility लें जो घटनाओं के साथ WaitHandles का उपयोग करता है।

+0

की सहायता के लिए धन्यवाद मैंने ऑटोआरसेट एवेन्ट्स का उपयोग किया: – Robar

6

आप आमतौर पर सत्यापित करें (expr, बार) तरीकों के साथ conjuction में अपनी व्यवस्था के सत्यापन-() का उपयोग नहीं करते। यदि आप हटाते हैं तो यह काम करता है। सत्यापित() कॉल?

+0

अगर मैं .Verifiable हटाने() कॉल मुझे निम्न त्रुटि मिलती है: 'नकली पर अपेक्षित आमंत्रण बिल्कुल 1 बार, लेकिन 0 बार था: f => f.CreateFinish (It.IsAny (), It.IsAny ()) कॉन्फ़िगर किए गए सेतु पुनश्च: च => f.CreateFinish (It.IsAny (), It.IsAny ()), Times.Never प्रदर्शन किया अनुरोध: IFactory.LoadPlan ("TestPlanDoNotUse") ' – Robar

+0

कि एक छोटे से लग रहा है बेहतर, अगर यह वास्तव में पूरा त्रुटि संदेश है। अब ऐसा लगता है कि CreateFinish को अभी कॉल नहीं किया जाता है। क्या यह CreateFinish के लिए किए गए आमंत्रणों के बारे में कुछ भी कहता है? – TheFogger

+0

नहीं, यह CreateFinish के चालान के बारे में कुछ भी नहीं कहा, लेकिन मैंने इसे डीबग किया और मुझे लगता है कि मुझे समस्या मिली है: मेरा जवाब देखें। – Robar

2

मुझे लगता है कि यह एक बहुत ही जवाब है, लेकिन मुझे विश्वास है कि यह पहले उल्लेख किए गए कई लोगों की तुलना में एक आसान समाधान है।

public static void WaitFor(Func<bool> action, long timeoutMillis = 10000) { Stopwatch elapsed = Stopwatch.StartNew(); elapsed.Start(); // ReSharper disable once LoopVariableIsNeverChangedInsideLoop while (!action()) { if (elapsed.ElapsedMilliseconds > timeoutMillis) { throw new TimeoutException("Timed out waiting for condition to become true after " + elapsed.ElapsedMilliseconds + " ms"); } Thread.Sleep(0); } }

और परीक्षण कोड इस तरह दिखता है:

मैं एक WaitFor समारोह जो एक लैम्ब्डा कॉलबैक का इस्तेमाल करता है एक स्थिति का मूल्यांकन करने के लिए लागू

[Test] 
    public void ShouldNackUnparsableInboundMessage() 
    { 
     var nackCalled = false; 
     _mock.Setup(m => m.BasicNack(999, false, false)).Callback(() => 
     { 
      nackCalled = true; 
     }); 

     ... do whatever which invokes the call on another thread. 

     WaitFor(() => nackCalled); 
     // Test will fail with timeout if BasicNack is never called. 
    } 
संबंधित मुद्दे