Search code examples
aws-lambdaamazon-cloudwatchfluentvalidationaws-event-bridgefakeiteasy

Mocking an AWS ScheduledEvent class using C# .NET


I am trying to verify that data coming in the Detail property of an AWS ScheduledEvent object is correct. The information should be coming in from EventBridge with JSON in the Detail property that matches this class:

public class EventBatchData
{
    public int BatchSize { get; private set; }
    public int BatchRetries { get; private set; }

    public EventBatchData(int batchSize, int batchRetries)
    {
        BatchSize = batchSize;
        BatchRetries = batchRetries;

        var validator = new EventBatchDataValidator();
        validator.ValidateAndThrow(this);
    }
}

I have a FluentValidation validator in the class so it cannot be created in an invalid state.

However, I am not able to set the SceduledEvent.Detail property, either directly or as an expectation through a mocking library. The Detail property is defined with type T so I even tried using dynamic but that fails:

[Theory]
    [AutoFakeItEasyData]
    public void NotThrowError_WhenDetailIsValid(EventBatchData eventBatchData)
    {
        //Arrange
        dynamic expectedDetail = new ExpandoObject();
        expectedDetail.BatchRetries = eventBatchData.BatchRetries;
        expectedDetail.BatchSize = eventBatchData.BatchSize;

        var scheduledEvent = new ScheduledEvent
        {
            Account = "testAccount",
            Region = "testRegion",
            DetailType = "Scheduled Event",
            Source = "aws.events",
            Time = DateTime.UtcNow,
            Id = "cdc73f9d-aea9-11e3-9d5a-835b769c0d9c",
            Resources = new List<string> { "resource1", "resource2" },
            Detail = expectedDetail
        };

        //Act
        var result = _validator.TestValidate(scheduledEvent);

        //Assert
        result.ShouldHaveValidationErrorFor(x => x.Detail);
    }

Cannot implicitly convert type 'System.Dynamic.ExpandoObject' to 'Amazon.Lambda.CloudWatchEvents.ScheduledEvents.Detail'


Solution

  • The ScheduledEvent class actually inherits from the CloudWatchEvent<Amazon.Lambda.CloudWatchEvents.ScheduledEvents.Detail> class, so the Details field is not a generic data type; instead, it is type of Amazon.Lambda.CloudWatchEvents.ScheduledEvents.Detail class.

    Hence, you cannot use the dynamic data type for the Details field; instead, convert the EventBatchData class to the Details data type, and it should work.

    public class EventBatchData : Amazon.Lambda.CloudWatchEvents.ScheduledEvents.Detail 
    {
        public int BatchSize { get; private set; }
        public int BatchRetries { get; private set; }
    
        public EventBatchData(int batchSize, int batchRetries)
        {
            BatchSize = batchSize;
            BatchRetries = batchRetries;
    
            var validator = new EventBatchDataValidator();
            validator.ValidateAndThrow(this);
        }
    }