Can you help me understand Moq Callback?
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
In Moq, Callback lets you run custom code when a mocked method is invoked. It is most useful when you want to capture arguments, simulate side effects, or inspect how the system under test interacts with a dependency beyond a simple "was this method called" check.
The key idea is that Callback attaches behavior to a setup. It does not replace Returns or Verify; it complements them when the test needs to observe something happening at call time.
Start with a Simple Setup
Suppose a service sends a message through a dependency:
You can use Callback to capture the values passed in:
This is helpful when you want to inspect arguments after the call, especially if the assertion logic is easier to read outside the setup expression.
Callback Runs When the Method Is Invoked
Callback executes at the moment the mocked member is called. That means it is good for:
- capturing method arguments
- incrementing counters
- mutating external test state
- simulating side effects such as storing data in a fake collection
For example, a repository mock can append saved items to a test list:
That makes the mock behave a little like a tiny in-memory fake while still being configured with Moq.
Callback and Returns Often Work Together
For methods that return a value, Callback and Returns can be chained:
Here Callback records that the call happened, while Returns provides the result.
When Verify Is Enough
Do not use Callback just to prove a method was called once with certain arguments. Moq already has Verify for that:
Verify is usually cleaner for pure interaction assertions. Reach for Callback when the test needs to capture, transform, or accumulate data during invocation.
That distinction keeps tests readable. If every expectation is implemented through side effects in a callback, the test becomes harder to scan.
Use It Carefully
Because Callback can mutate outside state, it is easy to write brittle tests with too much hidden behavior. A good rule is:
- use
Verifyfor straightforward interaction assertions - use
Returnsfor outputs - use
Callbackonly for call-time side effects the test genuinely needs
That keeps mocks focused and prevents a setup chain from turning into a mini program.
Common Pitfalls
- Using
CallbackwhenVerifywould express the assertion more clearly. - Forgetting that the generic parameters in
Callback<T1, T2>must match the mocked method signature. - Hiding too much test logic inside callbacks and making tests hard to understand.
- Expecting
Callbackto return a value. It performs side effects;Returnscontrols the result.
Summary
- '
Callbackruns custom code when a mocked member is invoked.' - It is useful for capturing arguments and simulating side effects.
- '
Callbackoften pairs withReturnsbut serves a different purpose.' - Use
Verifywhen you only need to assert that a call happened. - Keep callbacks small so the mock setup stays readable and predictable.

