Mocking
When dealing with asynchronous messaging, it can be challenging to determine precisely when a
message will be consumed. This is where the use of CancellationTokenSource
becomes essential.
To manage these waiting operations, you have two options. The first is to use the UnmockAndWait
extension,
which allows you to wait for a mocked method's completion. However, this approach has some limitations:
the mocked method can have a maximum of six arguments, and the return type must be either Task
or Task<TResult>
.
The design is intentionally userfriendly.
fixture.UnmockAndWait<IAvroHandlingService, bool, IncomingKafkaMessage, CancellationToken>(
fixture.ServiceMock,
src => src.EnrichAndPublishChangeEvent(It.IsAny<IncomingKafkaMessage>(),
It.IsAny<CancellationToken>()),
cts);
In this example:
The first generic parameter is the type of the service, repository, or other managing object.
The second generic parameter is the return type of the method if it returns Task<TResult>
. If the method returns Task
, this parameter is omitted.
The first argument is the mocked object.
The second argument is a delegate for Moq's
Returns method.
The third argument is a CancellationTokenSource
, used to cancel the wait for message consumption.
The fourth argument, which is optional, is a TimeSpan
for an additional delay, what is useful when working with databases.
The remaining generic parameters specify the types of the arguments in the mocked method.
Note: Avoid mocking MediatR
calls unless you are familiar with its workings.
Advanced Usage
If the UnmockAndWait
extensions do not meet your needs, you can use a more flexible mechanism that provides greater control.
In this case, manually set up your mock and use the UseBaseImplementationAndCancelToken
extension. This method takes a generic
parameter of the service, repository, or other managing object. The first argument is a delegate that performs the action on the object,
the second is the CancellationTokenSource
, and the third is an optional TimeSpan
to define an additional delay.
fixture.SampleMongoRepoMock.Setup(s => s.InsertSampleModel(It.IsAny<SampleMongoModel>(), It.IsAny<CancellationToken>()))
.Returns((SampleMongoModel model, CancellationToken ct) =>
{
return fixture.UseBaseImplementationAndCancelToken<ISampleMongoRepository>(
src => src.InsertSampleModel(model, ct),
cts,
TimeSpan.FromSeconds(2));
});