2015-09-15 32 views
5

Tôi hiện đang viết một ứng dụng và để kiểm tra hành vi đúng của nó, tôi cần xác minh rằng các phương thức được gọi theo một thứ tự nhất định.Đang cố gắng hiểu MockSequence

Đối với đơn vị xét nghiệm của tôi, tôi đang sử dụng xUnitMoq

Bây giờ, tại sao tôi cần phải kiểm tra thứ tự mà các cuộc gọi đang được thực hiện?

Tôi đang phát triển một giải pháp thực hiện các tác vụ trên các chuỗi khác nhau. Ngay sau khi một nhiệm vụ được thực hiện, tôi đang viết một thông báo cho một trình ghi cụ thể, vì vậy bằng cách kiểm tra thứ tự mà các cuộc gọi đến trình ghi nhật ký được thực hiện, tôi chắc chắn rằng mã của tôi đã được triển khai chính xác.

Xem ở đây mã mà tôi đang cố gắng để sử dụng:

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(); 
    } 
} 

Vì vậy, bước đầu tiên trong thử nghiệm của tôi là để thiết lập các bản ghi, sau đó kiểm tra bản thân được thực hiện (điều này gây ra các cuộc gọi đến các logger) và cuối cùng tôi đang xác minh nó.

Tuy nhiên, thử nghiệm không vượt qua luôn.

Nó nên thất bại trong trường hợp này kể từ khi cuộc gọi sau đây:

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

là không thực hiện bất cứ nơi nào trong mã của tôi.

+4

Xem [issue # 75] (https://github.com/Moq/moq4/issues/75), đây có thể là hành vi mong đợi. –

+0

@PatrickQuirk Liên kết tuyệt vời. Nhưng nếu bạn nhìn vào các ý kiến ​​chủ đề từ ngày 2 tháng 1 năm 2014, nó được thống nhất rằng có hai vấn đề (có nghĩa là Moq "lỗi" ở đó). Những gì phức tạp kinh nghiệm trong mã của mình ở trên, là "vấn đề 1" của họ. –

Trả lời

1

Trong khi điều này chắc chắn cảm thấy giống như một lỗi trong Moq (xem bình luận đầu tiên cho câu hỏi, bởi Patrick Quirk), đây là một ý tưởng thô cho những gì bạn có thể làm thay vào đó. Đây là một loại "bình luận dài".

Tạo một lớp đơn giản như:

class SequenceTracker 
{ 
    int? state; 

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

     state = newState; 
    } 
} 

Sau đó sử dụng nó như thế này (phiên bản sửa đổi của mã của riêng bạn):

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(); 
} 

Tất nhiên điều này có thể được thực hiện tiến bộ hơn nếu muốn.

Các vấn đề liên quan