0

Is there a preferred way to mock deeply-nested types when testing TypeScript apps?

I'm using the @types/aws-lambda package, and it has lots of types like this:

export interface S3EventRecord {
    eventVersion: string;
    eventSource: string;
    awsRegion: string;
    eventTime: string;
    eventName: string;
    userIdentity: {
        principalId: string;
    };
    requestParameters: {
        sourceIPAddress: string;
    };
    responseElements: {
        'x-amz-request-id': string;
        'x-amz-id-2': string;
    };
    s3: {
        s3SchemaVersion: string;
        configurationId: string;
        bucket: {
            name: string;
            ownerIdentity: {
                principalId: string;
            };
            arn: string;
        };
        object: {
            key: string;
            size: number;
            eTag: string;
            versionId?: string | undefined;
            sequencer: string;
        };
    };
    glacierEventData?: S3EventRecordGlacierEventData | undefined;
}

Naturally, I don't care about a lot of these properties during my unit tests, and would like to mock them out with dummy data in an easy way.

I've looked around but can't seem to find any libraries for my purpose.

I have played around with the Partial<Type>, but it doesn't seem to suit my purpose due to this S3EventRecord being held as an array in yet another type.

jonrsharpe
  • 115,751
  • 26
  • 228
  • 437
Sam
  • 1,234
  • 3
  • 17
  • 32
  • Related: https://stackoverflow.com/a/69771198/3001761 – jonrsharpe Apr 08 '22 at 13:53
  • If the code you're testing doesn't need all of the fields, maybe its types should reflect that? For example, make a function accept a smaller interface instead of this huge interface provided by the library. – decorator-factory Apr 08 '22 at 13:55
  • 1
    Mocking means replacing components (or behaviours of components) that do lengthy operations, that access the disk/network/database, that return random values or depend on the current date&time, with components that have fast and deterministic behaviour that can be configured in tests as needed. Why would you mock a data type? If you replace in tests the real type with a simplified type, how do you know that the code is able to deal correctly with the real type? – axiac Apr 08 '22 at 13:58
  • In this case, the `S3EventRecord` is handed to my lambda function handler by AWS. I think it's better that I use the type directly from their package, so I know that i'm not modifying the type incorrectly. However, I don't need all of it, just a slice for each specific unit test. It'd be nice to have the full object, populated with just the values I need for the test. The rest could just be empty strings, or 0's etc. Of course, I can do this myself in the test suite, I was just wondering if anyone had run into this before and figured out a more elegant solution? – Sam Apr 08 '22 at 14:04
  • I've suggested two such solutions in the linked answer - interface segregation, so you have a slice _related_ to the upstream type, and a helper to build a complete (but trivial) object from a partial one. – jonrsharpe Apr 08 '22 at 14:27
  • Thanks @jonrsharpe, definitely a good solution. I mainly wondered if anyone had developed a library to build this kind of thing depending on the type, rather than have to build those helper functions for each use case. The example you give is a small type, but as the question shows, they can have many properties and be deeply nested. – Sam Apr 11 '22 at 06:26

0 Answers0