Home > database >  How to unit Test Lambda functions in Mockito?
How to unit Test Lambda functions in Mockito?

Time:11-04

I have a lambda handler which triggers whenever for every S3Event.

s3Event.getRecords().forEach(record->{
        final String bucket = record.getS3().getBucket().getName();
        final String object = record.getS3().getObject().getKey();
        S3Object s3Object = amazonS3.getObject(bucket, object);
    
            ... More parsing logic

So in order to test this function, I have created Mock S3Event builder which would build a mock S3Event for me. Also

S3Event s3Event = buildS3Event(S3_BUCKET_NAME, S3_FILE_NAME);
    List<S3EventNotification.S3EventNotificationRecord> mockRecords = s3Event.getRecords();
    S3EventNotification.S3EventNotificationRecord mockFirstRecord = s3Event.getRecords().get(0);
    S3EventNotification.S3Entity mockS3Entity = mockFirstRecord.getS3();
    S3EventNotification.S3BucketEntity mockS3BucketEntity = mockS3Entity.getBucket();
    S3EventNotification.S3ObjectEntity mockS3ObjectEntity = mockS3Entity.getObject();
    String bucketName = mockS3BucketEntity.getName();
    String keyName = mockS3ObjectEntity.getKey();

BuildS3Event, getMockS3Bocket are utility function that I have used to to create respective mocks.

Class mocks as well:

    s3Client = Mockito.mock(AmazonS3.class);
    s3Object = Mockito.mock(S3Object.class);
    s3EventMock = Mockito.mock(S3Event.class);
    notificationRecord = Mockito.mock(S3EventNotification.S3EventNotificationRecord.class);
    notificationRecords = Mockito.mock(List.class);
    s3Entity = Mockito.mock(S3EventNotification.S3Entity.class);
    s3BucketEntity = Mockito.mock(S3EventNotification.S3BucketEntity.class);
    s3ObjectEntity = Mockito.mock(S3EventNotification.S3ObjectEntity.class);

    when(s3EventMock.getRecords()).thenReturn(mockRecords);

    handler.handle(s3Event, null) <--- calling the handler 
    verify(s3EventMock, times(1)).getRecords(); // seems to work
    verify(notificationRecords, times(1)).get(0); // fails with wanted but not invoked error.

Am I missing something while mocking?

CodePudding user response:

I would move the lambda's content to a separate method, which could be tested directly:

public void someMethod() {
   s3Event.getRecords().forEach(this::parse);
}

void parse(...) {
   ...
}

This would also improve the readability, since lambdas with more then one line are harder to read then a method reference that has a self-explanatory name.

  • Related