Using Moq to determine if a method is called
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
Moq verification is a standard way to confirm that one unit called a dependency method with expected arguments. Correct verification helps ensure behavior, not only output, especially in services that coordinate repositories, queues, or external clients. The key is to verify meaningful interactions and avoid brittle over-verification.
Basic Verify Pattern
Create a mock, execute the method under test, and assert invocation count.
This verifies that the interaction happened exactly once with expected values.
Verify with Flexible Argument Matching
When exact body text is not important, use argument matchers.
This keeps tests robust when incidental formatting changes.
Verify No Unexpected Calls
VerifyNoOtherCalls helps catch accidental side effects.
Use this selectively. In highly collaborative services, strict no-other-calls checks can become brittle during legitimate refactoring.
Asynchronous Methods
For async dependencies, verify invocation after awaiting the SUT method.
Always await async methods to avoid false negatives caused by race timing.
Design Better Verifications
Verify interactions that represent business behavior, not implementation trivia. For example, verifying repository save call is useful; verifying every logger call often is not.
Good tests usually combine:
- State assertion where applicable.
- One or two interaction assertions on critical collaborators.
- Minimal coupling to internal method order.
Setup and Callback Techniques
Sometimes you need to capture invocation arguments for deeper assertions. Moq callbacks make this straightforward.
This complements Verify when you need richer assertions than simple call count.
Ordered Interaction Verification
If order matters across dependencies, use explicit sequencing patterns. Keep this only for workflows where order is part of business behavior.
Overusing order assertions makes tests fragile, so reserve them for critical flows.
Strict Versus Loose Mocks
Moq defaults to loose behavior. Strict mocks throw on unconfigured calls.
Strict mode can catch accidental calls early, but it increases maintenance cost. Choose based on team preference and test scope.
Practical Test Design Guidance
A strong interaction test usually has one responsibility. Keep arrange data small, execute one action, and assert only essential interactions. This keeps failure messages clear and reduces false positives during refactors.
Common Pitfalls
- Verifying too many internal calls and making tests fragile.
- Forgetting to await async methods before verification.
- Using overly broad
It.IsAnyand missing argument bugs. - Asserting exact call counts when behavior is intentionally idempotent.
- Treating interaction verification as replacement for result assertions.
Summary
- Use
Verifyto assert critical dependency interactions. - Match arguments precisely where behavior depends on them.
- Use
VerifyNoOtherCallscarefully for strict boundaries. - Await async flows before asserting invocation.
- Keep verifications behavior-focused, not implementation-heavy.

