2015-09-15 6 views
5

को समझने की कोशिश कर रहा हूं मैं वर्तमान में एक एप्लिकेशन लिख रहा हूं और इसके सही व्यवहार का परीक्षण करने के लिए मुझे यह सत्यापित करने की आवश्यकता है कि दिए गए क्रम में विधियों को बुलाया जाता है।MockSequence

मेरी यूनिट टेस्ट के लिए, मैं xUnit और Moq

उपयोग कर रहा हूँ अब, कारण है कि मैं जिस क्रम में किए जा रहे हैं कॉल का परीक्षण करने की जरूरत है?

मैं एक समाधान विकसित कर रहा हूं जो विभिन्न धागे पर कार्यों को निष्पादित करता है। जैसे ही कोई कार्य निष्पादित हो जाता है, मैं किसी दिए गए लॉगर को एक संदेश लिख रहा हूं, इसलिए ऑर्डर की जांच करके जिसमें लॉगजर को कॉल किया जाता है, मुझे यकीन है कि मेरा कोड सही ढंग से लागू किया गया था।

यहाँ देखें कोड जो मैं कोशिश कर रहा हूँ उपयोग करने के लिए:

public class SchedulerFixture 
{ 
    #region Constructors 

    public SchedulerFixture() 
    { 
     LoggerMock = new Mock<ILogger>(MockBehavior.Strict); 

     // Setup of other mocks removed for simplicity. 
    } 

    #endregion 
} 

public class SequentialTaskExecutorMock : SchedulerFixture 
{ 
    [Fact] 
    public void Should_WriteTheCorrectLogEntries_WhenTasksAreExecutedAndNotCancelled() 
    { 
     // Defines the task that needs to be executed. 
     var task = new LongRunningServiceTaskImplementation(); 

     // Built a sequence in which logs should be created. 
     var sequence = new MockSequence(); 

     LoggerMock.Setup(x => x.Information(It.IsAny<string>(), It.IsAny<string>())).Verifiable(); 

     LoggerMock.InSequence(sequence).Setup(x => x.Information("émqsdlfk", "smdlfksdmlfk")).Verifiable(); 
     LoggerMock.InSequence(sequence).Setup(x => x.Information(LoggingResources.LoggerTitle, LoggingResources.Logger_ServiceStopped)).Verifiable(); 
     LoggerMock.InSequence(sequence).Setup(x => x.Information(LoggingResources.LoggerTitle, LoggingResources.Logger_ServiceStarted)).Verifiable(); 
     LoggerMock.InSequence(sequence).Setup(x => x.Information(LoggingResources.LoggerTitle, string.Format(CultureInfo.InvariantCulture, LoggingResources.Logger_TaskCompleted, task.TaskName))).Verifiable(); 
     LoggerMock.InSequence(sequence).Setup(x => x.Information(LoggingResources.LoggerTitle, LoggingResources.Logger_ServiceStopped)).Verifiable(); 

     // Setup the mock required for the tests. 
     TaskGathererMock.Setup(x => x.GetServiceTasks(LoggerMock.Object)).Returns(() => 
     { 
      return new[] { task }; 
     }); 

     // Start the scheduler. 
     Scheduler.Start(TaskGathererMock.Object, ConfigurationManagerMock.Object); 

     // Wait for 5 seconds (this simulates running the service for 5 seconds). 
     // Since our tasks execution time takes 4 seconds, all the assigned tasks should have been completed. 
     Thread.Sleep(5000); 

     // Stop the service. (We assume that all the tasks have been completed). 
     Scheduler.Stop(); 

     LoggerMock.VerifyAll(); 
    } 
} 

तो, अपने परीक्षण में पहला कदम सेटअप करने के लिए है लॉग, तो परीक्षण ही निष्पादित किया जाता है (इस लकड़हारा के लिए कॉल का कारण बनता है) और अंत में मैं इसे सत्यापित कर रहा हूं।

हालांकि, परीक्षण हमेशा पास होता है।

यह निम्नलिखित कॉल के बाद इस मामले में असफल चाहिए:

LoggerMock.InSequence(sequence).Setup(x => x.Information("émqsdlfk", "smdlfksdmlfk")).Verifiable(); 

मेरी कोड में कहीं भी क्रियान्वित नहीं है।

+4

देखें [मुद्दा # 75] (https://github.com/Moq/moq4/issues/75), यह व्यवहार की उम्मीद की जा सकती है। –

+0

@PatrickQuirk ग्रेट लिंक। लेकिन यदि आप 2 जनवरी 2014 से थ्रेड टिप्पणियों को देखते हैं, तो यह इस बात पर सहमत है कि दो मुद्दे हैं (जिसका मतलब है कि वहां मक "बग" है)। उपरोक्त कोड में क्या जटिलता अनुभव है, उनका "मुद्दा 1" है। –

उत्तर

1

हालांकि यह सुनिश्चित है कि मोक में एक बग की तरह लगता है (पैट्रिक क्विर्क द्वारा प्रश्न पर पहली टिप्पणी देखें), यहां एक अजीब विचार है कि आप इसके बजाय क्या कर सकते हैं। यह एक "लंबी टिप्पणी" की तरह है।

एक साधारण वर्ग की तरह बनाओ:

class SequenceTracker 
{ 
    int? state; 

    public void Next(int newState) 
    { 
     if (newState <= state) 
      Assert.Fail("Bad ordering there! States should be increasing."); 

     state = newState; 
    } 
} 

फिर इस (अपने खुद के कोड के संशोधित संस्करण) की तरह उपयोग:

public void Should_WriteTheCorrectLogEntries_WhenTasksAreExecutedAndNotCancelled() 
{ 
    // Defines the task that needs to be executed. 
    var task = new LongRunningServiceTaskImplementation(); 

    // USE THE CLASS I PROPOSE: 
    var tracker = new SequenceTracker(); 


    //LoggerMock.Setup(x => x.Information(It.IsAny<string>(), It.IsAny<string>())) 

    LoggerMock.Setup(x => x.Information("émqsdlfk", "smdlfksdmlfk")) 
     .Callback(() => tracker.Next(10)); 
    LoggerMock.Setup(x => x.Information(LoggingResources.LoggerTitle, LoggingResources.Logger_ServiceStopped)) 
     .Callback(() => tracker.Next(20)); 
    LoggerMock.Setup(x => x.Information(LoggingResources.LoggerTitle, LoggingResources.Logger_ServiceStarted)) 
     .Callback(() => tracker.Next(30)); 
    LoggerMock.Setup(x => x.Information(LoggingResources.LoggerTitle, string.Format(CultureInfo.InvariantCulture, LoggingResources.Logger_TaskCompleted, task.TaskName))) 
     .Callback(() => tracker.Next(40)); 
    LoggerMock.Setup(x => x.Information(LoggingResources.LoggerTitle, LoggingResources.Logger_ServiceStopped)) 
     .Callback(() => tracker.Next(50)); 

    // Setup the mock required for the tests. 
    TaskGathererMock.Setup(x => x.GetServiceTasks(LoggerMock.Object)).Returns(() => 
    { 
     return new[] { task }; 
    }); 

    // Start the scheduler. 
    Scheduler.Start(TaskGathererMock.Object, ConfigurationManagerMock.Object); 

    // Wait for 5 seconds (this simulates running the service for 5 seconds). 
    // Since our tasks execution time takes 4 seconds, all the assigned tasks should have been completed. 
    Thread.Sleep(5000); 

    // Stop the service. (We assume that all the tasks have been completed). 
    Scheduler.Stop(); 

    // THIS NOW WORKS BECAUSE WE ABANDONED THE 'MockSequence' APPROACH: 
    LoggerMock.VerifyAll(); 
} 

बेशक यह अगर वांछित और अधिक उन्नत बनाया जा सकता है।