2009-04-20 28 views
57

tôi muốn thiết lập một giá trị trả vềLàm thế nào để xóa các kỳ vọng trước đó về một đối tượng?

_stubRepository.Stub(Contains(null)).IgnoreArguments().Return(true); 

nhưng sau đó trong một thử nghiệm cụ thể, ghi đè lên kỳ vọng rằng để trả về false.

Cái gì như:

_stubRepository.ClearExpectations(); //<- this does not exist, I'm just making something up 
_stubRepository.Stub(Contains(null)).IgnoreArguments().Return(false); 

Thông báo, tôi không muốn sự mong đợi để trả về false vào cuộc gọi thứ hai, tôi muốn ghi đè lên sự mong đợi đầu tiên.

Điều này sẽ giúp đơn giản hóa kịch bản thử nghiệm của tôi rất nhiều.

Trả lời

67

Có ba cách:

Bạn có thể thiết lập lại sự mong đợi bằng cách sử dụng BackToRecord

Tôi phải thừa nhận rằng tôi không bao giờ thực sự sử dụng nó bởi vì nó là khó xử.

// clear expectations, an enum defines which 
_stubRepository.BackToRecord(BackToRecordOptions.All); 
// go to replay again. 
_stubRepository.Replay(); 

Edit: Bây giờ tôi sử dụng nó đôi khi, nó thực sự là cách sạch nhất. Nên có một phương pháp mở rộng (như Stub) mà nó - tôi nghĩ rằng nó chỉ bị lãng quên. Tôi sẽ đề nghị để viết của riêng bạn.

Bạn có thể sử dụng Repeat.Any()

Nó 'phá vỡ' trật tự của định nghĩa stubbed và "ghi đè" định nghĩa trước. Nhưng nó bằng cách nào đó ngầm. Tôi sử dụng nó đôi khi bởi vì nó rất dễ dàng để viết.

_stubRepository.Stub(x => x.Contains(null)) 
    .IgnoreArguments() 
    .Return(false) 
    .Repeat.Any(); 

Bạn có thể tạo mới mock

Trivial, nhưng rõ ràng và dễ hiểu. Nó chỉ là vấn đề nếu bạn muốn giữ nhiều định nghĩa và chỉ thay đổi một cuộc gọi.

_stubRepository = MockRepository.GenerateMock<IRepository>(); 
_stubRepository.Stub(x => x.Contains(null)) 
    .IgnoreArguments() 
    .Return(false); 
+0

Trong nội bộ Rhino Mock nói, sử dụng Lặp lại. Bất kỳ tạo ra một kỳ vọng lặp lại, mà trump mong đợi bình thường trong quá trình phát lại. Tuy nhiên, tôi khuyên bạn nên sử dụng BackToRecord. –

+0

Ah, đã tìm ra tất cả ngoại trừ cuộc gọi Replay(). –

+1

Đây là một điều chỉ thực sự được biết đến bởi những người sử dụng RhinoMocks từ 3.4 trở lên. RhinoMocks làm việc với Record-Replay, điều này có nghĩa là một mô hình phải được đặt vào chế độ phát lại một cách rõ ràng. Với 3,5, may mắn thay điều này đã biến mất, mocks luôn ở chế độ phát lại (ít nhất là cho mã tùy chỉnh). Cho đến khi bạn đưa nó trở lại chế độ kỷ lục - ngoại trừ việc thanh toán bù trừ, tôi không thấy lý do gì để làm điều đó. Tôi đã muốn viết một bản vá cho hai dòng này để đặt lại kỳ vọng một cách thoải mái. –

22

Đối với những trường hợp này, tôi đã tạo một phương pháp mở rộng RinoMocks đơn giản để thể hiện rõ hơn ý định của bài viết và tăng cường khả năng đọc.

public static void OverridePrevious<T>(this IMethodOptions<T> options) 
{ 
    options.Repeat.Any(); 
} 

Vì vậy, thay vì một cuộc gọi bí ẩn như sau đó có thể yêu cầu một lời nhận xét:

[SetUp] 
public void Setup() 
{ 
    carStub.Stub(x => x.Model).Return("Model1"); 
    carStub.Stub(x => x.Model).Return("Model2"); 
} 

[Test] 
public void SomeTest() 
{ 
    //Arrange 
    //overrides previous stubs that were setup for the Model property 
    carStub.Stub(x => x.Model).Return(null).Repeat.Any(); 

    //Act 
    //Assert 
} 

Bạn có thể nhận được một bài kiểm tra dễ đọc hơn mà chương trình tốt hơn mục đích của .Repeat.Any() cuộc gọi :

carStub.Stub(x => x.Model).Return(null).OverridePrevious(); 
+5

Để giữ cho tùy chọn mở để chuỗi cấu hình sơ khai, không nên phương pháp mở rộng trả về một IMethodOptions ? 'public static IMethodOptions OverridePrevious (tùy chọn này IMethodOptions ) {return options.Repeat.Any(); } '. – PHeiberg

+2

@PHeiberg - Tôi chưa thử hoặc có nhu cầu giữ 'chuỗi mở' nhưng có, tôi cho rằng bạn đúng. Điểm tốt. – MoMo

+0

Tôi thích OverridePrevious như void - nó buộc nó đến cùng. – user2864740

5

Vì lợi ích của cộng đồng tôi sẽ thêm này để thêm vào danh sách các tùy chọn ở trên Stefan:

Nếu giá trị trả lại cần phải được thay đổi thường xuyên, tôi thấy nó sạch sẽ và hiệu quả để sử dụng đóng cửa như sau.

bool returnValue = true; 
_stubRepository.Stub(x => x.Contains(null)).IgnoreArguments().Do(new Func<bool>(() => { 
    return returnValue; 
})); 

returnValue = false; 
// Calls to Contains now return false; 

returnValue = true; 
// Calls to Contains now return true; 

Biểu thức lambda sẽ được thực hiện mỗi khi Contains được gọi và bởi vì chúng tôi đã tạo ra một đóng cửa tham khảo returnValue, nó sẽ luôn luôn tìm kiếm các giá trị hiện của returnValue.

+0

Đây là giải pháp sạch nhất theo ý kiến ​​của tôi –

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