Azure / azure-sdk-for-net

This repository is for active development of the Azure SDK for .NET. For consumers of the SDK we recommend visiting our public developer docs at https://learn.microsoft.com/dotnet/azure/ or our versioned developer docs at https://azure.github.io/azure-sdk-for-net.
MIT License
5.26k stars 4.6k forks source link

Make EventDataBatch mockable. #21024

Closed bbondarets closed 3 years ago

bbondarets commented 3 years ago

Hi there. While working with this library i've faced with difficulties in testing code that uses this package because some of it's parts are not mockable. For example, EventDataBatch from Azure.Messaging.EventHubs.Producer is a sealed class hence it can't be mocked. Also it doesn't has any interface that defines him so that's why it's also impossible to fake it as well.

image

It would be great if you could somehow fix this. Thanks in advance, Bohdan.

jsquire commented 3 years ago

Hi @bbondarets. Thank you for reaching out and we regret that you're experiencing difficulties. Support for mocking and unit testing is one of the core goals of the new Azure SDKs, and the details of the approach that we use is discussed in the Azure SDK Design Guidelines.

Each of the Azure SDKs has a model factory class that allows creation of the types returned from service operations that can't be directly created. In this case, you can use the EventHubsModelFactory to create a batch intended for mocking. In addition to the model factory, each of the client types are unsealed, have a parameterless constructor, and all of the public members are either virtual or settable. Our intent is to ensure that it is usable with a mocking library such as Moq or FakeItEasy.

You should be able to mock any client using the same approach that you prefer for other types, whether with a mocking framework or inheriting from the class and creating your own mock type, using the model factory to simulate behavior.

If you're seeing other unit testing gaps that we haven't considered, we'd be very interested in your specific scenarios so that we can take them into account and improve the experience.

bbondarets commented 3 years ago

Hey @jsquire, thanks for your reply. Really appreciate it. EventHubsModelFactory is cool indeed, however from my point of view it should have ability to pass max bytes size as constructor parameter. In our case we do some batching logic using EventDataBatch.TryAdd method. As far as it's not available for direct mocking i would like to set 1kb as max batch size for batch that i've created via EventHubsModelFactory. It could be nice oppotunity instead of mocking EventDataBatch.TryAdd method and setting up it's return value to false. However max size is big indeed and this makes some difficulties in testing. image

I Hope i didn't miss anything from your advices. Thanks, i'm looking forward for your reply.

jsquire commented 3 years ago

Hi @bbondarets. The model factory allows you to pass a set of CreateBatchOptions when creating a mock batch, using the same type that the actual CreateBatchAsync call does. In these options is your MaximumSizeInBytes parameter, which allows you to specify the maximum size.

For example:

var reportedBatchSize = 12;
var batchOptions = new CreateBatchOptions { MaximumSizeInBytes = 50 };
var batch = EventHubsModelFactory.EventDataBatch(reportedBatchSize, new List<EventData>(), batchOptions);

Produces a batch that looks like:

image

bbondarets commented 3 years ago

@jsquire that solves my problem. Thanks a lot.