Какой самый лаконичный способ использовать Moq для издевательства над методом, который будет генерировать исключение при первом вызове, а затем выполнить второй раз, когда он вызывается?
Moq: Настройте посмеянный метод сбой при первом вызове, преуспеть на втором
Ответ 1
Я бы использовал Callback
и увеличил счетчик, чтобы определить, нужно ли исключать исключение из Callback
.
[Test]
public void TestMe()
{
var count = 0;
var mock = new Mock<IMyClass>();
mock.Setup(a => a.MyMethod()).Callback(() =>
{
count++;
if(count == 1)
throw new ApplicationException();
});
Assert.Throws(typeof(ApplicationException), () => mock.Object.MyMethod());
Assert.DoesNotThrow(() => mock.Object.MyMethod());
}
public interface IMyClass
{
void MyMethod();
}
Ответ 2
Лучшее, что я придумал до сих пор, это:
interface IFoo
{
void Bar();
}
[Test]
public void TestBarExceptionThenSuccess()
{
var repository = new MockRepository(MockBehavior.Default);
var mock = repository.Create<IFoo>();
mock.Setup(m => m.Bar()).
Callback(() => mock.Setup(m => m.Bar())). // Setup() replaces the initial one
Throws<Exception>(); // throw an exception the first time
...
}
Ответ 3
Фил Хаак имеет интересное сообщение о настройке метода для возврата определенной последовательности результатов. Похоже, что это была бы хорошая отправная точка с некоторой работой, потому что вместо последовательности значений определенного типа вам нужно было бы иметь последовательность результатов, которые могут иметь тип T или исключение.
Ответ 4
Начиная с Moq 4.2 вы можете просто использовать встроенный метод SetupSequence()
(как указано комментарием @RichardBarnett).
Пример:
var mock = new Mock<IMyClass>();
mock.SetupSequence(x => x.MyMethod("param1"))
.Throws<MyException>()
.Returns("test return");