0

I have this twilio.service.ts file. I want to write a unit test in twilio.service.spec.ts for two cases in which the verification OTP has been sent successfully or failed with missing parameters.

twilio.services.ts:

  async startVerification(
   startVerificationDto: StartVerificationDto
   ) {
    try {
      const verificationResponse = await this.twilioClient.verify
        .services("TWILIO_VERIFY_SERVICE_SID")
        .verifications.create({
          to: `+91${sendVerificationCodeDto.phoneNumber}`,
          channel: "sms",
          locale: "en",
        });
      return verificationResponse;
    } catch (error) {
      throw new BadRequestException("Failed sending OTP");
    }
  }

It tried so far:

it("Should be able to send verification code on mobile number", async () => {
    const actualRes = await controller.startVerification({
      phoneNumber: "xxxxxxxxxxx",
    });

    expect(twilioService.twilioClient.verify.services).toBeCalledWith(
      "TWILIO_VERIFY_SERVICE_SID"
    );

    expect(actualRes).toEqual({
      sid: "VA_TWILIO_VERIFY_SERVICE_SID",
    });
  });



  it("Should return error if required parameters are missing", async () => {

    expect(twilioService.twilioClient.verify.services).not.toBeCalledWith(
      "TWILIO_VERIFY_SERVICE_SID"
    );

    try {
      await controller.startVerification({
        phoneNumber: "xxxxxxxxxxx",
      });
    } catch (e) {
      expect(e.message).toBe("Failed sending OTP");
    }
  });

My main concern is: how to mock nested functions of Twilio (verify>service>verification>create). Also, after mocking how do I call or use that in spec.ts file.

kartik tyagi
  • 6,256
  • 2
  • 14
  • 31

1 Answers1

1

Twilio developer evangelist here.

Mocking nested objects and function calls is more annoying than difficult. I think something like this should work for you:

(I'm not sure the relationship between the controller and the twilioService in your example. I've tried to mock the twilioClient on the twilioService here, but you may need to adjust that based on how things fit together.)

it("Should be able to send verification code on mobile number", async () => {
  const mockVerificationCreate = jest.fn().mockResolvedValue({
    sid: "VA_TWILIO_VERIFY_SERVICE_SID"
  })
  const mockVerifyService = jest.fn().mockReturnValue({
    verifications: {
      create: mockVerificationCreate
    }
  })
  twilioService.twilioClient = {
    verify: {
      services: mockVerifyService
    }
  }
 
  const actualRes = await controller.startVerification({
    phoneNumber: "xxxxxxxxxxx",
  });

  expect(twilioService.twilioClient.verify.services).toBeHaveBeenCalledWith(
    "TWILIO_VERIFY_SERVICE_SID"
  );
  expect(mockVerificationCreate).toHaveBeenCalledWith({
    to: "+91xxxxxxxxxxx",
    channel: "sms",
    locale: "en",
  });
  expect(actualRes).toEqual({
    sid: "VA_TWILIO_VERIFY_SERVICE_SID",
  });
});

Let me know if that helps.

philnash
  • 70,667
  • 10
  • 60
  • 88
  • thanks, @philnash to response. here `services` in `twilioService.twilioClient = { verify: { services: mockVerifyService } }` is throwing a typescript error stated: `Type 'Mock' is missing the following properties from type 'ServiceListInstance': create, each, get, getPage, and 3 more.ts(2740) Verify.d.ts(25, 12): The expected type comes from property 'services' which is declared here on type 'Verify' `. How to resolve this? – kartik tyagi Jun 11 '21 at 07:58