我们将测试以下GraphQL解析器,它有授权和许可检查。如果用户没有经过认证,解析器会返回一个错误。如果数据库实体的要求没有得到满足,解析器会返回一个错误。否则,解析器会创建一个新的数据库实体。
export default {
Mutation: {
createFreeCourse: async (
parent,
{ courseId, bundleId },
{ me }
) => {
if (!me) {
return new Error('Not authenticated as user.');
}
const price = getPrice(courseId, bundleId);
if (price !== 0) {
return new Error('This course is not for free.')
}
await createCourse({
uid: me.uid,
courseId,
bundleId,
amount: 0,
paymentType: 'FREE',
});
return true;
},
},
};
如果我们使用GraphQL解析器中间件(这是可选的),它可以被简化为以下内容。
export default {
Mutation: {
createFreeCourse: combine(
isAuthenticated,
isFreeCourse,
async (parent, { courseId, bundleId }, { me }) => {
await createCourse({
uid: me.uid,
courseId,
bundleId,
amount: 0,
paymentType: 'FREE',
});
return true;
}
),
},
};
无论如何,让我们跳到用Jest测试这个GraphQL解析器。我们用所有的参数调用解析器函数,并期望在所有的要求都得到满足时将其返回的承诺解析为真。
import resolvers from './';
describe('createFreeCourse', () => {
it('creates a course', async () => {
const result = resolvers.Mutation.createFreeCourse(
null,
{
courseId: 'THE_ROAD_TO_GRAPHQL',
bundleId: 'STUDENT',
},
{ me: { uid: '1', email: 'example@example.com' } },
null
);
await expect(result).resolves.toEqual(true);
});
});
如果你需要用Jest来模拟数据库请求,请查看这个关于Jest模拟的教程。一旦你模拟了你的数据库API,你可以在你的测试案例中添加更多的断言。
import resolvers from './';
describe('createFreeCourse', () => {
it('creates a course', async () => {
const result = resolvers.Mutation.createFreeCourse(
null,
{
courseId: 'THE_ROAD_TO_GRAPHQL',
bundleId: 'STUDENT',
},
{ me: { uid: '1', email: 'example@example.com' } },
null
);
await expect(result).resolves.toEqual(true);
expect(mockedSet).toHaveBeenCalledTimes(1);
expect(mockedSet).toHaveBeenCalledWith({
courseId: 'THE_ROAD_TO_GRAPHQL',
packageId: 'STUDENT',
invoice: {
createdAt: 'TIMESTAMP',
amount: 0,
licensesCount: 1,
currency: 'USD',
paymentType: 'FREE',
},
});
});
});
不管怎样,让我们保持测试用例的简单性,不要有数据库断言。到目前为止,我们只测试了满足所有要求的解析器逻辑的快乐路径。如果用户没有被认证呢?
describe('createFreeCourse', () => {
it('creates a course', async () => {
...
});
it('does not create a course if not authenticated', async () => {
const result = resolvers.Mutation.createFreeCourse(
null,
{
courseId: 'THE_ROAD_TO_GRAPHQL',
bundleId: 'STUDENT',
},
{ me: null },
null
);
await expect(result).resolves.toEqual(
new Error('Not authenticated as user.')
);
});
});
通常情况下,我们期望承诺会被拒绝。然而,在 GraphQL 中,我们成功地将错误作为解析结果返回。这样,我们也可以测试 GraphQL 解析器的其他条件逻辑。
describe('createFreeCourse', () => {
it('creates a course', async () => {
...
});
it('does not create a course if not authenticated', async () => {
...
});
it('does not create a course if not free', async () => {
const result = resolvers.Mutation.createFreeCourse(
null,
{
courseId: 'THE_ROAD_TO_GRAPHQL',
bundleId: 'PROFESSIONAL',
},
{ me: { uid: '1', email: 'example@example.com' } },
null
);
await expect(result).resolves.toEqual(
new Error('This course is not for free.')
);
});
});
这就是它。GraphQL解析器最终只是函数。你可以在你的测试文件中导入它们,调用解析器,并执行断言。通过设置授权和许可解析器,你也可以在出错时测试不开心的路径。最后,GraphQL服务器会返回一个承诺,无论是成功的结果还是错误。