2011-12-28 23 views
10

Có thể thử nghiệm ví dụ sau nếu Method1 được gọi là 1st, sau đó Method2 gọi sau và sau đó Method3 bằng cách sử dụng cú pháp AAA, trong Rhino-mocks 3.6?Tôi có thể kiểm tra lệnh gọi phương thức với cú pháp AAA trong Rhino-Mocks 3.6 không?

// Assert 
var mock = MockRepository.GenerateMock<ISomeService>(); 

// Act 
myObject.Service = mock; 

// How should I change this part to ensure that Rhino Mocks check the call order as well? 
mock.AssertWasCalled(m=>m.Method1()); 
mock.AssertWasCalled(m=>m.Method2()); 
mock.AssertWasCalled(m=>m.Method3()); 

Trả lời

19

Dưới đây là một cách để làm điều đó ...

mock.AssertWasCalled(m=>m.Method1(), options => options.WhenCalled(w => mockService.AssertWasNotCalled(x=>x.Method2()))); 
mock.AssertWasCalled(m=>m.Method2(), options => options.WhenCalled(w => mockService.AssertWasNotCalled(x=>x.Method3()))); 
mock.AssertWasCalled(m=>m.Method3()); 
8

Bạn có thể, nhưng bạn thực sự không nên. Bạn nên tập trung vào việc kiểm tra các hành vi quan sát được bên ngoài, thay vì thực hiện.

Lệnh gọi phương thức có thể thay đổi mà không ảnh hưởng đến hợp đồng với khách hàng của API. Trong trường hợp đó, kiểm tra của bạn sẽ thất bại, ngay cả khi nó không nên.

Tóm lại, việc triển khai thử nghiệm dẫn đến các thử nghiệm giòn. Các xét nghiệm giòn dẫn đến việc từ bỏ các xét nghiệm. Bạn không muốn đến đó.

Hy vọng điều này sẽ hữu ích.

+16

Điều này không phải luôn luôn như vậy. Có những hợp đồng của các đối tượng statefull nơi đặt hàng các vấn đề và bạn có thể không phải luôn luôn tránh những hợp đồng. – sanosdole

+0

Tôi đồng ý với nhận xét của @sanosdole nhưng trong trường hợp của tôi, bạn đã phát hiện ra. Tôi nên thử nghiệm kết quả ... chứ không phải việc thực hiện. Cảm ơn! – MoMo

+0

Nếu mã đã có khớp nối thời gian, nó cũng cần được kiểm tra. – SerG

5

Đây là cách để làm điều đó một cách độc đáo.

var mocks = new MockRepository(); 
var fooMock = mocks.DynamicMock<IFoo>(); 
using (mocks.Ordered()) 
{ 
    fooMock.Expect(x => x.Method1()); 
    fooMock.Expect(x => x.Method2()); 
} 
fooMock.Replay(); 

var bar = new Bar(fooMock); 
bar.DoWork(); 

fooMock.VerifyAllExpectations(); 

Tìm thấy câu trả lời from this blog.

+0

Tôi đã phải sửa đổi điều này một chút để có được nó để làm việc trong RhinoMocks 3.5 - xem câu trả lời của tôi dưới đây. – Clarkeye

+0

Không phải cú pháp AAA. – SerG

1

Dưới đây là làm thế nào để làm điều đó bằng cách xây dựng khẳng định vào từng phương pháp gọi.

// Arrange - Build the necessary assertions into the stubbed method invocations. 
var mock = MockRepository.GenerateMock<ISomeService>(); 
mock.Stub(m => m.Method1()).WhenCalled(inv => mock.AssertWasNotCalled(m => m.Method2())); 
mock.Stub(m => m.Method2()).WhenCalled(inv => mock.AssertWasNotCalled(m => m.Method3())); 

// Act 
myObject.Service = mock; 

// Assert - Ensure each expected method was called. 
mock.AssertWasCalled(m => m.Method1()); 
mock.AssertWasCalled(m => m.Method2()); 
mock.AssertWasCalled(m => m.Method3()); 

Do đây là hỗn hợp lên bình thường mô hình sắp xếp-hành-khẳng định bằng cách chạy khẳng định vào giữa hành động, tôi muốn bao gồm các thông báo lỗi rất cụ thể đối với những trường hợp này để xác định thất bại kiểm tra dễ dàng hơn.

mock.Stub(m => m.Method1()).WhenCalled(inv => 
    mock.AssertWasNotCalled(m => m.Method2(), opt => 
     opt.Message("Method2 cannot be called before Method1."))); 

Bạn cũng có thể đạt được kết quả tương tự bằng cách lưu kết quả của mỗi lời gọi trong biến trong bước hành động và sau đó kiểm tra trạng thái biến trong bước xác nhận. Điều này tốt hơn bảo tồn sự phân chia của mô hình sắp xếp-hành động-khẳng định, nhưng nó là nhiều hệ thống ống nước mã để viết và duy trì.

// Arrange - Build the necessary state variables into the stubbed method invocations. 
bool wasMethod1Called; 
bool wasMethod2Called; 
bool wasMethod2CalledBeforeMethod1; 
bool wasMethod3CalledBeforeMethod2; 

var mock = MockRepository.GenerateMock<ISomeService>(); 
mock.Stub(m => m.Method1()).WhenCalled(inv => 
{ 
    wasMethod1Called = true; 
}); 
mock.Stub(m => m.Method2()).WhenCalled(inv => 
{ 
    wasMethod2Called = true; 
    wasMethod2CalledBeforeMethod1 = !wasMethod1Called; 
}); 
mock.Stub(m => m.Method3()).WhenCalled(inv => 
{ 
    wasMethod3CalledBeforeMethod2 = !wasMethod2Called; 
}); 

// Act 
myObject.Service = mock; 

// Assert - Ensure each expected method was called, and that they were called in the right order. 
mock.AssertWasCalled(m => m.Method1()); 
mock.AssertWasCalled(m => m.Method2()); 
mock.AssertWasCalled(m => m.Method3()); 
Assert.That(wasMethod2CalledBeforeMethod1, Is.False, "Method2 cannot be called before Method1."); 
Assert.That(wasMethod3CalledBeforeMethod2, Is.False, "Method3 cannot be called before Method2."); 
0

Các mocks.Ordered() Cú pháp theo quy định của @craastad là đúng cách để làm điều đó, nhưng tôi không thể làm cho nó làm việc trong RhinoMocks 3.5 - thay vào đó tôi đã phải tinh chỉnh nó để làm việc mà không có ví dụ của MockRepository rằng @ giải pháp craastad của sử dụng để gọi Ordered() trên:

var fooMock = MockRepository.GenerateMock<IFoo>(); 
using (fooMock.GetMockRepository().Ordered()) 
{ 
    fooMock.Expect(x => x.Method1()); 
    fooMock.Expect(x => x.Method2()); 
} 

var bar = new Bar(fooMock); 
bar.DoWork(); 

fooMock.VerifyAllExpectations(); 

Nếu bạn làm theo cách này, nó cũng dường như là không cần thiết để gọi fooMock.Replay() một trong hai.

+3

Ai đó đã đánh dấu câu trả lời này, điều này là công bằng, nhưng nếu bạn định làm điều đó thì ít nhất bạn có thể giải thích tại sao! – Clarkeye

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