2011-10-27 29 views
7

Tôi đang sử dụng Moq như khuôn khổ mocking của tôi và tôi cần phải kiểm tra một lớp học khi một loại ngoại lệ cụ thể được chạy nó sẽ tiếp tục cố gắng cho đến khi tình hình được giải quyết một khi điều đó xảy ra việc thực hiện kết thúc.Làm thế nào để làm cho một giả ném một ngoại lệ lần đầu tiên và trả về một giá trị thứ hai

Vì vậy, những gì tôi cần là một cái gì đó tương tự như:

myMock = Mock<IFoo>(); 

myMock.Setup(m => m.Excecute()).Throws<SpecificException>(); 
myMock.Setup(m => m.Execute()); 

var classUnderTest = MyClass(myMock); 
classUnderTest.DoSomething(); 

Assert.AreEqual(expected, classUnderTest.Result); 

Nhờ sự giúp đỡ bạn có thể cho.

Trả lời

15

Đây là một cách, dựa trên ví dụ Moq QuickStart trả về các giá trị khác nhau cho mỗi lệnh gọi.

var mock = new Mock<IFoo>(); 
var calls = 0; 
mock.Setup(foo => foo.GetCountThing()) 
    .Returns(() => calls) 
    .Callback(() => 
    { 
     calls++; 
     if (calls == 1) 
     { 
      throw new InvalidOperationException("foo"); 
     } 
    }); 

try 
{ 
    Console.WriteLine(mock.Object.GetCountThing()); 
} 
catch (InvalidOperationException) 
{ 
    Console.WriteLine("Got exception"); 
} 

Console.WriteLine(mock.Object.GetCountThing()); 

Nếu phương pháp này trả về void, sử dụng:

var myMock = new Mock<IFoo>(); 
bool firstTimeExecuteCalled = true; 

myMock.Setup(m => m.Execute()) 
     .Callback(() => 
     { 
      if (firstTimeExecuteCalled) 
      { 
       firstTimeExecuteCalled = false; 
       throw new SpecificException(); 
      } 
     }); 

try 
{ 
    myMock.Object.Execute(); 
} 
catch (SpecificException) 
{ 
    // Would really want to call Assert.Throws instead of try..catch. 
    Console.WriteLine("Got exception"); 
} 

myMock.Object.Execute(); 
Console.WriteLine("OK!"); 
+0

Điều đó có vẻ thú vị nhưng, nếu phương pháp này là void và tôi không nhận được phương thức "Trả về" sau khi thiết lập? Và thực tế nó hoạt động nếu "GetCountThing" trả về một int, nó sẽ không biên dịch nếu nó trả về cái gì khác. –

+0

@SergioRomero - vui lòng xem câu trả lời đã chỉnh sửa. – TrueWill

+0

Đối với nếu nó không phải là một int, thay đổi những gì bạn đang trở về từ dòng 'Returns'. Nó không phải là giá trị của 'cuộc gọi'. – TrueWill

1

Tại sao không thực sự viết đối tượng thử nghiệm của riêng bạn mà thực hiện điều này? Nếu nó chỉ sẽ được sử dụng để thử nghiệm tức là một cái gì đó như:

public class Mock : IFoo 
{ 
    private int _calls; 

    public Mock() 
    { 
     _calls = 0; 
    } 

    public int Execute() 
    { 
     _calls++; 

     if (_calls == 1) 
      throw new Exception(); 

     return value; 

    } 

} 
+1

Trong trường hợp này tôi có thể thấy điều đó. Đây là một trường hợp cạnh, mặc dù; hầu hết thời gian tôi hoặc muốn có một nhánh sẽ trả về các giá trị không đổi đã biết hoặc một mô hình sẽ xác minh rằng một phương thức đã cho đã được gọi. Moq làm cho nó rất dễ dàng để tạo ra cả hai những người trên bay. Ngoài ra, nếu bạn có một giao diện cũ với 30 thành viên và chỉ cần một trong số chúng cho thử nghiệm này, giải pháp Moq ngắn hơn nhiều. – TrueWill

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