1

我正在使用 Typescript 设置一个带有graphql-yoga和 `prisma 的 graphql 服务器。当用户注册时,一封带有验证链接的电子邮件将被发送到给定的电子邮件地址。一切正常,但我想在重构功能之前为突变编写一个测试,检查 SendGrid 的“发送”函数是否已被调用。

我尝试用 监视函数jest.spyOn,但我得到的只是一个错误,这是因为在测试环境中没有为 SendGrid 提供 API 密钥。

我以前使用过 spyOn,它确实有效,尽管这是我第一次将 jest 与 Typescript 一起使用。

注册突变

import * as sgMail from '@sendgrid/mail';

sgMail.setApiKey(process.env.MAIL_API_KEY);

export const Mutation = {
    async signUpUser(parent, { data }, { prisma }, info) {
        [...]
        const emailData = {
            from: 'test@test.de',
            to: `${user.email}`,
            subject: 'Account validation',
            text: `validation Id: ${registration.id}`
        };
        await sgMail.send(emailData);

        return user;
    }
}

尝试间谍

import * as sgMail from '@sendgrid/mail';

const signUpUserMutation = gql`
    mutation($data: ValidationInput) {
        signUpUser (data: $data) {
            id
            email
        }
    }
`;

it('should send a registration email, with a link, containing the id of the registration', async () => {
    spyOn(sgMail, "send").and.returnValue(Promise.resolve('Success'));
    const variables = {
        data: {
            email: "test@test.de",
            password: "anyPassword"
        }
    };

    await client.mutate({ mutation: signUpUserMutation, variables});
    expect(sgMail.send).toHaveBeenCalled();
});

运行测试给了我:

错误:GraphQL 错误:未经授权

注释掉突变中的 send 函数调用并运行测试给了我:

错误:expect(spy).toHaveBeenCalled()

预期 spy 已被调用,但未调用。

4

1 回答 1

1

您没有@sendgrid/mail以正确的方式模拟模块。这就是错误发生的原因。这是不使用GraphQL测试客户端的解决方案。但是您可以在正确模拟模块后使用GraphQL测试客户端来测试您的GraphQL解析器和GraphQL架构。@sendgrid/mail

mutations.ts

import * as sgMail from '@sendgrid/mail';

sgMail.setApiKey(process.env.MAIL_API_KEY || '');

export const Mutation = {
  async signUpUser(parent, { data }, { prisma }, info) {
    const user = { email: 'example@gmail.com' };
    const registration = { id: '1' };
    const emailData = {
      from: 'test@test.de',
      to: `${user.email}`,
      subject: 'Account validation',
      text: `validation Id: ${registration.id}`
    };
    await sgMail.send(emailData);

    return user;
  }
};

mutations.spec.ts

import { Mutation } from './mutations';
import * as sgMail from '@sendgrid/mail';
import { RequestResponse } from 'request';

jest.mock('@sendgrid/mail', () => {
  return {
    setApiKey: jest.fn(),
    send: jest.fn()
  };
});

describe('Mutation', () => {
  describe('#signUpUser', () => {
    beforeEach(() => {
      jest.resetAllMocks();
    });
    it('should send a registration email, with a link, containing the id of the registration', async () => {
      (sgMail.send as jest.MockedFunction<typeof sgMail.send>).mockResolvedValueOnce([{} as RequestResponse, {}]);
      const actualValue = await Mutation.signUpUser({}, { data: {} }, { prisma: {} }, {});
      expect(actualValue).toEqual({ email: 'example@gmail.com' });
      expect(sgMail.send).toBeCalledWith({
        from: 'test@test.de',
        to: 'example@gmail.com',
        subject: 'Account validation',
        text: `validation Id: 1`
      });
    });
  });
});

覆盖率 100% 的单元测试结果:

 PASS  src/stackoverflow/56379585/mutations.spec.ts (12.419s)
  Mutation
    #signUpUser
      ✓ should send a registration email, with a link, containing the id of the registration (23ms)

--------------|----------|----------|----------|----------|-------------------|
File          |  % Stmts | % Branch |  % Funcs |  % Lines | Uncovered Line #s |
--------------|----------|----------|----------|----------|-------------------|
All files     |      100 |      100 |      100 |      100 |                   |
 mutations.ts |      100 |      100 |      100 |      100 |                   |
--------------|----------|----------|----------|----------|-------------------|
Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        14.315s

这是完成的演示:https ://github.com/mrdulin/jest-codelab/tree/master/src/stackoverflow/56379585

于 2019-09-26T06:21:42.237 回答