我正在使用Typescript用graphql-yoga和pyramida设置graphql服务器。用户注册后,带有验证链接的电子邮件将发送到给定的电子邮件地址。一切工作正常,但我想在重构功能之前编写一个针对突变的测试,该功能检查是否未调用SendGrid的“发送”功能。
我尝试使用spyOn监视该函数,但是得到的只是一个错误,原因是在测试环境中未提供SendGrid的API密钥。
我以前使用过spyOn,并且可以正常工作,尽管这是我第一次在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: '[email protected]',
to: `${user.email}`,
subject: 'Account validation',
text: `validation Id: ${registration.id}`
};
await sgMail.send(emailData);
return user;
}
}
尝试spyOn
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: "[email protected]",
password: "anyPassword"
}
};
await client.mutate({ mutation: signUpUserMutation, variables});
expect(sgMail.send).toHaveBeenCalled();
});
运行测试给了我:
Error: GraphQL error: Unauthorized
注释出send的函数调用并运行测试给了我:
Error: expect(spy).toHaveBeenCalled()
Expected spy to have been called, but it was not called.
您没有以正确的方式嘲笑@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: '[email protected]' };
const registration = { id: '1' };
const emailData = {
from: '[email protected]',
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: '[email protected]' });
expect(sgMail.send).toBeCalledWith({
from: '[email protected]',
to: '[email protected]',
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