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

Callback and Argument Capturing

Capture arguments passed to mocks to perform complex validations on passed objects.

In this lesson, you will learn how to intercept and store arguments passed to your mocks, enabling deep inspection of object state that occurs deep within a method call.

The Problem: Beyond Simple Verification

While Verify is excellent for checking that a method was called, it struggles when you need to inspect the internal properties of a complex object that was instantiated or modified inside the method under test. If you need to validate specific values inside an object passed to a dependency, standard verification falls short. This is where Argument Capturing (using Capture) and Callbacks come into play.

Capturing Arguments

Argument capturing allows you to "grab" the object being passed to a mock so you can assert against it after the execution phase. Using Moq, you define an ArgumentCaptor and bind it to your mock setup.

var captor = new ArgumentCaptor<UserRequest>();
mockService.Setup(s => s.Process(captor.Capture()));

// Act: Execute the method under test
systemUnderTest.Execute(input);

// Assert: Access the captured object directly
var captured = captor.Value;
captured.Username.Should().Be("DevUser");
captured.Timestamp.Should().BeCloseTo(DateTime.Now, precision: 100);

Leveraging Callbacks

Sometimes, capturing isn't enough—you might need to trigger side effects or perform logic when a mock is invoked. A Callback allows you to execute an arbitrary delegate whenever the mock is called. This is perfect for capturing arguments that are passed multiple times or to verify the state of an object at the exact moment the call occurs.

UserRequest capturedRequest = null;

mockService.Setup(s => s.Process(It.IsAny<UserRequest>()))
           .Callback<UserRequest>(req => capturedRequest = req);

systemUnderTest.Execute(input);

// Now perform deep assertions on the captured state
capturedRequest.Permissions.Should().Contain("Admin");

By combining these techniques, you move from testing simple interactions to verifying complex state transitions within your dependencies. You are no longer just checking if the code "called the service"; you are validating that the data sent to that service is architecturally sound.

Key Takeaway: Use Argument Capturing and Callbacks to extract and inspect the internal state of objects passed to mocks, allowing for precise validation of complex data flows that simple verification cannot reach.