Возвращение разных результатов или исключение из последовательных вызовов в Moq Mock

Я получаю объект Moq для возврата разных значений при последовательных вызовах метода. Это делается с помощью этого метода расширения:

public static void ReturnsInOrder<T, TResult>(this ISetup<T, TResult> setup, params TResult[] results) where T : class
{
    setup.Returns(new Queue<TResult>(results).Dequeue);
}

Теперь я хочу, чтобы один из вызовов вызывал исключение, а другие возвращали что-то. Кто-нибудь сделал это раньше?

Если я делаю это

mock.Setup(m => m.SomeMethod())
    .Throws(new Exception());
mock.Setup(m => m.SomeMethod())
    .Returns("ok");

то первая настройка будет перезаписана, и сохраняется только вторая настройка.

Ответы

Ответ 1

Я использовал цепочку обратного вызова при разработке прокси-сервера retry.

var src = new Mock<ITest>();
src.Setup(s => s.RaiseError()).Callback(() => 
src.Setup( s => s.RaiseError())).Throws<Exception>();

const int retryCount = 1;
var proxy = RetryProxy.MakeFor(src.Object, retryCount);

proxy.RaiseError();
src.Verify(s => s.RaiseError(), Times.Exactly(retryCount+1));

Ответ 2

В настоящее время Moq (версия 4+) поддерживает это методом SetupSequence. См. этот пост для введения.

Ответ 4

Используйте SetupSequence(...) для макетного объекта.

Например, следующее вызовет исключение при первом вызове и вернет someResponse во второй вызов:

myService.SetupSequence(s => s.PlaceOrder())
    .Throws(new Exception())
    .Returns(someResponse);