Guide to simulating Twilio with Jest and TypeScript to perform unit testing

Please assist me in mocking a Twilio service that sends messages using Jest to mock the service. Below is the code I am working with:

import { SQSEvent } from "aws-lambda";
import { GetSecretValueResponse } from "aws-sdk/clients/secretsmanager";

export async function sendSms(event: SQSEvent, data: GetSecretValueResponse) {
    const secrets = JSON.parse(data.SecretString);
    const accountSid = secrets.TWILIO_ACCOUNT_SID;
    const authToken = secrets.TWILIO_AUTH_TOKEN;
    const twilioNumber = secrets.TWILIO_PHONE_NUMBER;

    if (accountSid && authToken && twilioNumber) {
        //Create a Twilio Client
        const client = new Twilio(accountSid, authToken);
        //Loop through all records of the event, where each record represents a message sent from Sqs
        for (const record of event.Records) {
            const body = JSON.parse(record.body);
            const userNumber = "+" + body.number;
            //SendMessage function
            try {
                const message = client.messages.create({
                    from: twilioNumber,
                    to: userNumber,
                    body: body.message,
                });
                return message;
            } catch (error) {
                return `Failed to send sms message. Error Code: ${error.errorCode} / Error Message: ${error.errorMessage}`;
            }
        }
    } else {
        return "You are missing one of the variables you need to send a message";
    }
}

Then I call this function from my index:

I have already conducted some tests, however, they always connect to the actual Twilio API (requiring real token, sid, etc.), and I need to mock the Twilio service so that the function called in my test.ts does not connect to the internet.

(event and data are simulated responses of SqsEvent and GetSecretValueResponse)

When running npm test, it throws an error related to Twilio's authentication because I am passing self-created tokens.

Hence, what I suspect is that the test is making an internet connection and calling the Twilio API.

Your assistance in resolving this issue is greatly appreciated.

Answer №1

To mimic the class that the module returns, you should utilize

jest.mock('twilio', mockImplementation)
. In the mockImplementation function, create a constructor function that accepts your account SID and auth token as arguments. This constructor function should then return a mockClient implementation. The mockClient object needs to have a messages property, which is an object containing a create property that is a mock function.

The easiest way to understand this concept is by looking at the code example below.

const mockClient = {
  messages: {
    create: jest.fn().mockResolvedValue({ ...smsMessageMock });
  }
};

jest.mock("twilio", () => {
  return function(accountSid, authToken) {
    return mockClient;
  }
});

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

The binding element 'params' is assumed to have a type of 'any' by default

I encountered an issue The binding element 'params' implicitly has an 'any' type. Below is the code snippet in question: export default function Page({ params }) { const { slug } = params; return ( <> <h1>{s ...

Mocking a React component with Jest's MockImplementation

Currently, I am in the process of testing a react component that renders another component. This secondary component makes an API call to fetch data which is then displayed on the screen. My goal is to understand how I can mock this particular component&ap ...

What is the best way to send a Rails AJAX form upon clicking?

I'm looking to implement AJAX form submission in Rails using a button. Here's my current code: Controller: def list @events = ExternalEvent.all if !params[:city_id].nil? @events = @events.where(city_id: params[:city_id]) end respond ...

The password-protected HTML blog remains hidden until the correct entry is entered into the password box, causing

After successfully creating a password redirect page where entering the correct password redirects you to another URL (psswrdtest.tumblr.com with the password as correctpsswrd, redirecting to google.com*), I attempted to improve it by making the password p ...

Cover the entire screen with numerous DIV elements

Situation: I am currently tackling a web design project that involves filling the entire screen with 60px x 60px DIVs. These DIVs act as tiles on a virtual wall, each changing color randomly when hovered over. Issue: The challenge arises when the monitor ...

Would it be possible to continuously send multiple documents to MongoDB using a loop?

I'm facing difficulties in transmitting sensor data to MongoDB using JavaScript. Although I came across options like MongoDB Atlas, I am searching for a more straightforward way to accomplish this. Below is my code: const db = client.db(databaseName) ...

Modifying an element in an array while preserving its original position

Currently, I am working on updating the state based on new information passed through response.payload. Here is my existing code snippet: if(response.events.includes('databases.*.collections.*.documents.*.update')) { setMemos(prevState => pre ...

Trouble with Updating Div Content?

Within my HTML code, I have included this JavaScript snippet: <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.0/jquery.min.js"></script> <script> var auto_refresh = setInterval( function() { $('#loaddiv').fadeOut ...

What could be causing the absence of the exported Object when importing into a different Typescript project?

I am currently in the process of developing a React component library using Typescript that I want to import into another Typescript project. Specifically, I want to import an Analytics chart library into a storybook for demonstration and testing purposes. ...

I can't figure out why I'm receiving a TypeError stating that onSuccess is not a function within my AngularJS service

Utilizing an angularjs service that utilizes restangular for API calls. angular.module('app.userService', []) .factory('userService', ['localStorageService', '$rootScope', 'Restangular', func ...

What is the best method for setting up message scheduling for a Microsoft Teams bot based on different time

I am trying to figure out how to send messages to users from my bot at specific time intervals. Currently, I'm using agenda for scheduling messages, but I've run into an issue with the timezone discrepancy - agenda is 5:30 hours behind my timezon ...

Can you tell me the specific name of the HTML document style that features two columns?

Here are two websites that showcase a unique two-column style layout: http://momentjs.com/docs/ I find these sites visually appealing and I am curious about the specific name of this style. Is there a template or tool available to create documents with a ...

When velocity exceeds a certain threshold, collision detection may become unreliable

As I delve into detecting collisions between high-velocity balls, an obstacle arises. This issue seems to be quite common due to the nature of fast-moving objects colliding. I suspect that the solution lies within derivatives, and while I've drafted s ...

What is preventing me from generating Face3 in my ThreeJS Typescript project

Currently, I'm in the process of generating a Mesh using Face3 within a TypeScript project that utilizes Three.js. However, I've encountered a few issues along the way. const points = [ new Face3(-1, 1, -1),//c new Face3(-1, -1, 1),//b ...

Loading JS and CSS files in relation to the website root directory

When it comes to including CSS/JS files, what are the best practices for defining the file URI? Some people prefer to include files relative to the website root by specifying the full URI: <link rel="stylesheet" href="/my/path/to/css/main.css"> Thi ...

Activate an event on a shadow DOM element that is covered by an element in the light DOM (not directly related)

I am currently facing a challenge in retrieving the coordinates of a table cell within a shadow DOM. This table cell may have overlay elements displayed above it, which could span over multiple cells and may not necessarily be direct children of the cell I ...

What could be the reason my script fails to execute during an AJAX refresh?

As I was working on my project's avatar uploader, everything seemed to be going smoothly until this morning when chaos ensued. It was a moment of pure sadness. Initially, selecting a file would prompt the crop tool to appear immediately, and it worke ...

Utilizing a feature module imported from a separate Angular4 project

I have a question about setting up an Angular 4 project. Can feature modules be loaded from another Angular 4 project? I am currently attempting to maintain separate project repositories and dynamically load feature modules into the main project. This wa ...

Upon page refresh, products are automatically added to the cart

While developing a shopping cart code, I encountered an issue where refreshing the page automatically added a product to my cart without any action from me. For instance, my website displays three products: Apple, Banana, Orange. When I click on Apple, it ...

How to update deeply nested subdocuments in Mongoose

I am faced with an issue while attempting to update sub documents using mongoose by utilizing the request.body without explicitly passing the _id of the sub documents. Despite successfully updating, mongoose is deleting the _id from the sub documents. Con ...