Course contentsShow
← C#
Lesson 1633 of 1,90815. Software Quality and TestingFree lesson

Verifying Method Invocations

Verify that specific dependency methods were called with the correct arguments.

In this lesson, you will learn how to go beyond checking a method's return value by validating that your code correctly orchestrated its dependencies.

When testing behavior, it isn't enough to know that a service returned true; you often need to ensure it called a specific dependency, such as an IEmailService or IPaymentGateway, with the exact parameters required by your business logic. This is the cornerstone of behavioral verification.

The Behavioral Contract

Verifying invocations allows you to ensure your code "does what it says on the tin" regarding external interactions. If your OrderProcessor is supposed to send a confirmation email only when a payment succeeds, you need to verify that the Send method on your email mock was invoked exactly once with the specific recipient and subject.

Using a mocking framework like Moq, you can express this expectation after the "Act" phase of your AAA (Arrange-Act-Assert) pattern:

// Act
_processor.Process(order);

// Assert
_mockEmailService.Verify(
    service => service.Send(
        It.Is<string>(email => email == "customer@example.com"), 
        It.IsAny<string>()
    ), 
    Times.Once
);

Why Precision Matters

The power of Verify lies in its specificity. By using It.Is<T> predicates, you can enforce that your code correctly maps domain objects to dependency arguments. If the developer accidentally changes the email address parameter or calls the service twice, the test will fail, alerting you to a breach in the expected behavior.

However, a word of caution: avoid "over-verifying." If you verify every single internal call your code makes, your tests will become brittle and break whenever you refactor internal implementation details that don't affect the external outcome. Use verification to enforce critical side effects—like sending emails, writing to databases, or calling third-party APIs—rather than verifying every minor interaction that doesn't change the state of the system.

Key Takeaway: Use behavioral verification to ensure that critical side effects occur as expected, focusing on the intent and the correctness of arguments passed to your dependencies.