One of the most common tasks that were solved with callbacks is throwing an exception when a certain method is invoked with a given set of parameters.

var mock = new Mock<IService>();
mock.Setup(p => p.DoSomething())
.Callback(() => throw new Exception());

To streamline the configuration of methods throwing exceptions, Moq has special constructs targeting this scenario: Throws and ThrowsAsync.

Both methods accept an instance of any Exception type.

mock.Setup(p => p.DoSomething())
.Throws(new Exception("My custom exception"));
mock.Setup(p => p.DoSomethingAsync())
.ThrowsAsync(new Exception("My custom exception"));

Additionally, Throws can also instantiate an exception given its type.

mock.Setup(p => p.DoSomething())

Thows and ThrowsAsync can also be used in a sequence of calls.

mock.SetupSequence(p => p.GetSomeValue())
mock.SetupSequence(p => p.GetSomeValueAsync())
.ThrowsAsync(new Exception());

Throwing exceptions aware of incoming parameters

Unfortunately, Throws and ThrowsAsync have no overload accepting a delegate to be lazily evaluated.

The lack of such overloads makes it impossible to throw exceptions that are somehow aware of the incoming parameters.

The following statement is not supported.

mock.Setup(p => p.DoSomething(It.IsAny<int>()))
.Throws((int value) => new Exception($"{value} is not valid"));

The same behavior can be modeled with callbacks.

mock.Setup(p => p.DoSomething(It.IsAny<int>()))
.Callback((int value) => throw new Exception($"{value} is not valid"));