2012-05-23 26 views
18

Tôi đang tìm cách tìm ra cách tôi có thể thử phương thức trả về giá trị khác khi lần thứ hai được gọi thời gian. Ví dụ: một cái gì đó như thế này:RhinoMocks - chế nhạo một phương thức có giá trị trả về thay đổi (ngay cả khi chuyển cùng một thông số) với nhiều cuộc gọi

public interface IApplicationLifetime 
{ 
    int SecondsSinceStarted {get;} 
} 

[Test] 
public void Expected_mock_behaviour() 
{ 
    IApplicationLifetime mock = MockRepository.GenerateMock<IApplicationLifetime>(); 

    mock.Expect(m=>m.SecondsSinceStarted).Return(1).Repeat.Once(); 
    mock.Expect(m=>m.SecondsSinceStarted).Return(2).Repeat.Once(); 

    Assert.AreEqual(1, mock.SecondsSinceStarted); 
    Assert.AreEqual(2, mock.SecondsSinceStarted); 
} 

Có điều gì khiến điều này có thể xảy ra không? Bên cạnh việc thực hiện một phụ cho getter mà thực hiện một máy nhà nước?

Cheers fellas,

Alex

+0

Hãy xem các mocks đã đặt hàng và không có thứ tự: http://ayende.com/wiki/Rhino%20Mocks%20Ordered%20and%20Unordered.ashx – Maciej

+2

Có vấn đề gì với mã bạn đã cung cấp? 'Repeat.Once()' nên làm việc –

+0

@lazyberezovsky Cuộc gọi đầu tiên tới m.SecondsSinceStarted trả về 2, không 1 như mong đợi – AlexC

Trả lời

28

Bạn có thể đánh chặn các giá trị trở lại với .WhenCalled phương pháp. Lưu ý rằng bạn vẫn cần phải cung cấp giá trị thông qua .Return phương pháp, tuy nhiên Rhino sẽ chỉ đơn giản là bỏ qua nó nếu ReturnValue bị thay đổi từ phương pháp gọi:

int invocationsCounter = 1; 
const int IgnoredReturnValue = 10; 
mock.Expect(m => m.SecondsSinceLifetime) 
    .WhenCalled(mi => mi.ReturnValue = invocationsCounter++) 
    .Return(IgnoredReturnValue); 

Assert.That(mock.SecondsSinceLifetime, Is.EqualTo(1)); 
Assert.That(mock.SecondsSinceLifetime, Is.EqualTo(2)); 

Edit:

Đào xung quanh một chút, có vẻ như .Repeat.Once()không thực sự làm việc trong trường hợp này và có thể được sử dụng để đạt được cùng một kết quả:

mock.Expect(m => m.SecondsSinceStarted).Return(1).Repeat.Once(); 
mock.Expect(m => m.SecondsSinceStarted).Return(2).Repeat.Once(); 
mock.Expect(m => m.SecondsSinceStarted).Return(3).Repeat.Once(); 

Sẽ trả về 1, 2, 3 cho các cuộc gọi liên tiếp.

+0

Như tôi hiểu, đối với một cái gì đó khác với số tuần tự, ông nên tạo mảng và trả về giá trị theo chỉ mục? –

+0

Tôi đồng ý rằng phương pháp này hoạt động, nhưng điều này về cơ bản giống như phải triển khai máy trạng thái, mà tôi đã đề cập đến mà tôi đang cố gắng tránh (tức lànếu tôi muốn trả lại 11 trong lần gọi thứ hai, thì tôi cần phải làm một cái gì đó như "if (invocationsCounter == 1) return 1; else if (invocationsCounter == 2) return 11;" trông rất giống máy trạng thái. – AlexC

+0

Re: chỉnh sửa của bạn. Không chắc chắn nếu đây là một số chức năng đã thay đổi trong phiên bản RhinoMocks mà tôi đang sử dụng và phiên bản bạn đang sử dụng, nhưng tôi đã chạy thử nghiệm trong câu hỏi ban đầu của mình và có thể cho bạn biết nó không thành công (tức là cuộc gọi đầu tiên để SecondsSinceStarted trả về 2). Bạn có liên kết đến nơi bạn thấy rằng nó hoạt động không? – AlexC

0

Đã đến lúc yếu tố quyết định trong phương thức trả về? Nếu vậy, tôi sẽ cố gắng trừu tượng ra đoạn thời gian để bạn có thể kiểm soát trực tiếp nó trong các bài kiểm tra của bạn.

Giống như một giao diện gọi là ITimeProvider với thành viên có tên GetElapsedTime() và sau đó tạo triển khai mặc định để sử dụng trong suốt ứng dụng của bạn.

Sau đó, khi bạn đang thử nghiệm, hãy vượt qua một ITimeProvider giả lập để bạn kiểm soát những gì được ứng dụng của bạn nhận thấy là thời gian trôi qua.

+0

Thực sự, thời gian chỉ là một ví dụ hữu ích mà không mô tả đầy đủ những gì tôi đang cố gắng thử nghiệm. Mặc dù vậy, mặc dù vậy, nếu tôi muốn giả lập một ITimeProvider, có phương thức GetElapsedTime(), vấn đề vẫn tồn tại nếu tôi muốn viết một bài kiểm tra đơn vị gọi là GetElapsedTime() hai lần và muốn ITimeProvider giả của tôi trả về một thời gian cho mỗi cuộc gọi. – AlexC

+0

Bạn có thể có ITimeProvider là phụ thuộc thuộc tính không? Vì vậy, có thể tiêm mocks mới trước mỗi cuộc gọi? Mặc dù vậy, nếu không phải thời gian bạn đang đối phó, câu trả lời của tôi có thể vô giá trị ... – theMothaShip

+0

Câu hỏi của tôi là nhiều hơn về việc liệu RhinoMocks có hỗ trợ loại tương tác này với mocks/stub được tạo ra hay không và ít hơn về cách tôi có thể làm việc nó không được hỗ trợ. Cảm ơn mặc dù. – AlexC

5

Đơn giản chỉ cần sử dụng

mock.Expect(m=>m.SecondsSinceStarted).Return(1).Repeat.Once(); 
mock.Expect(m=>m.SecondsSinceStarted).Return(2).Repeat.Once(); 

này sẽ trở lại 1 trong suốt cuộc gọi đầu tiên, và 2 trong suốt cuộc gọi thứ hai. Ít nhất là trên RhinoMocks 3.6.0.0

+0

Điều này chắc chắn xung đột với những gì tôi thấy khi tôi chạy thử nghiệm trên – AlexC

+0

Như đã đề cập trong câu trả lời được chấp nhận, điều này là chính xác, thử nghiệm của tôi chỉ thất bại khi tôi bước qua và đánh giá một cái gì đó vô tình. Được thăng hạng. – AlexC

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