The Best Integration Testing Library for Serverless Projects Now Supports Typescript!
Tags: serverless, aws, typescript, testing
Published: 2022-03-01 07:57:57

**Local development** is an **anti-pattern** in the serverless world. If you're not convinced yet, have a look at Gareth McCumskey's [talk](https://dev.to/garethmcc/why-local-development-for-serverless-is-an-anti-pattern-1d9b) given at [Serverless Days Paris](https://paris.serverlessdays.io/fr/). 🎤

Having a local replica of the AWS resources deployed in production is not recommended as local emulations will not behave exactly like the production stack.

In this context, building a relevant integration testing strategy becomes painful as integration tests in a local environment do not guarantee a correct behavior in production.

Therefore, when it comes to integration tests, as a serverless developer you should:

- Avoid mocking serverless services and testing your application in a local environment ❌
- Use **real underlying serverless services** as much as possible to test your application ✅

How can you achieve that? 🤔
Using [**sls-test-tools**](https://github.com/aleios-cloud/sls-test-tools) 🏅 


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/grjyw2vsnswog59l16s1.png)

**sls-test-tools** provides custom Jest assertions to easily implement effective and high-quality **integration tests** for serverless architectures on AWS.


## 1️⃣  sls-test-tools was not typed 😭 but it now supports TypeScript 😍 ! 


sls-test-tools is a JS project and doesn’t provide types for TS developers. 🤯

However, at Kumo, our standard in terms of programming language for serverless projects is TypeScript.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5zmwkdnlce88x02dcxby.png)

Not having a tool to properly test our serverless TS projects has been an important issue for us in terms of developer experience and stability of our delivered applications.

So I **migrated sls-test-tools from JS to TS**; enabling the whole serverless/TS community to leverage sls-test-tools.


> 💡 I typed it using [ts-migrate](https://github.com/airbnb/ts-migrate)
> **ts-migrate** is a tool I strongly recommend. It's been developed by Airbnb to help to migrate easily JavaScript projects to TypeScript. 

The typed version of sls-test-tools has now been released (version 1.0.7 ) so:

- ⭐⭐⭐  sls-test-tools can be used in TS projects ⭐⭐⭐
- sls-test-tools API didn’t change for JS projects 🤝


## 2️⃣  New to sls-test-tools? Here is a quick tutorial


### Use case

As an example, let’s consider a lambda function that publishes an event containing client contact details on EventBridge.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cloxvey62d6k28362iuo.png)

```ts
export const handler = async (): Promise<string> => {
  const eventPayload = {
    id: 'clientId',
    email: 'client@mail.com',
  };

  await customerCreatedEvent.publish(eventPayload);

  return eventPayload.id;
};
```


#### Step 1

This lambda function firstly sets an Event payload.

```ts
  const eventPayload = {
    id: 'clientId',
    email: 'client@mail.com',
  };
```

This block could typically be replaced by data retrieved from any appropriate database service and some business logic.


#### Step 2

The lambda function publishes the event to an EventBridge bus.

```ts
await customerCreatedEvent.publish(eventPayload);
```


### Let’s test this!

To be sure that this lambda correctly publishes an event to the EventBridge bus, let’s write an **integration test** thanks to sls-test-tools.

```ts
import { AWSClient, EventBridge } from 'sls-test-tools';

const lambda = new AWSClient.Lambda();

describe('Event Bridge Integration Testing ', () => {
  it('correctly publishes an event to the event bus when the lambda is invoked', async () => {
    // Step 1: Arrange
    const eventBridge = await EventBridge.build(busName);

    // Step 2: Act
    await lambda.invoke({ FunctionName: lambdaName }).promise();

    // Step 3: Assert

    const eventBridgeEvents = await eventBridge.getEvents();
    
    expect(eventBridgeEvents).toHaveEvent();
    expect(eventBridgeEvents).toHaveEventWithSource('client');

    // Step 4: Clean
    await eventBridge.destroy();
  });
});
```


#### Step 1: Arrange - Update the real stack to run tests

```ts
const eventBridge = await EventBridge.build(busName);
```

Firstly, the build function provided by sls-test-tools is called. It checks that your stack includes an **EventBridge** bus with a given name. It also deploys an **SQS queue** used as a destination for all events sent in the bus. This queue is used to watch specific events for your Jest test asserts.


#### Step 2: Act - Execute the lambda

```ts
await lambda.invoke({ FunctionName: lambdaName }).promise();
```
Secondly, the lambda is executed.


#### Step 3: Assert - Expect real change on the stack

```ts
const eventBridgeEvents = await eventBridge.getEvents();
    
expect(eventBridgeEvents).toHaveEvent();
expect(eventBridgeEvents).toHaveEventWithSource('client');
```

Then, the getEvents function is called. It returns published messages present in the SQS queue which contain information about published events in EventBridge Bus. 

These messages are used to run two assertions to check that during the execution of the lambda:
- An event has been published to the bus
- An event has been published to the bus with a source value of _client_


#### Step 4: Clean - Discard any modification to the stack made during the test

```ts
await eventBridge.destroy();
```

Finally, the SQS queue is destroyed in order to clean the tested stack.


## 3️⃣  Next steps

Our team, with the support of [aleios](https://www.aleios.com/) and the community, is working on improving the DX of sls-test-tools (using environment variables instead of cli arguments...) and on adding more custom Jest assertions. We are also writing a more exhaustive article on Serverless integration testing, please feel free to subscribe so you can be notified when it will come out!

The community of sls-test-tools contributors is active and growing. Don’t hesitate to create an issue or open a PR if you want to get involved in the development of the project!