如何在 jest / apollo 客户端中捕获被拒绝的 graphql 订阅?
How to catch rejected graphql subscription in jest / apollo client?
我正在尝试使用 graphql-yoga 编写笑话测试来涵盖订阅。
我能够成功地测试快乐路径是订阅有效(使用授权)。不幸的是,我无法测试订阅 websocket 连接被拒绝的情况。
在我的服务器设置中,我拒绝任何未通过我的身份验证标准的 websocket 连接:
const app = await server.start({
cors,
port: process.env.NODE_ENV === "test" ? 0 : 4000,
subscriptions: {
path: "/",
onConnect: async (connectionParams: any) => {
const token = connectionParams.token;
if (!token) {
throw new AssertionError({ message: "NO TOKEN PRESENT" });
}
const decoded = parseToken(token, process.env.JWT_SECRET as string);
const user = await validateTokenVersion(decoded, redis);
if (user === {}) {
throw new AssertionError({ message: "NO VALID USER" });
}
return { user };
}
}
});
如我所愿,第一个测试(快乐之路)通过了:
// works as expected.
test("should start a subscription on network interface and unsubscribe", async done => {
const client = new TestClientApollo(process.env.TEST_HOST as string);
await client.register(email, password);
await User.update({ email }, { confirmed: true });
await client.login(email, password);
// set up subscription listener
const sub = client.client.subscribe(defaultOptions).subscribe({
next(result) {
expect(result).toEqual({
data: {
counter: {
count: 0
}
}
});
sub.unsubscribe();
done();
}
});
});
然后我尝试了 3 种不同的方法来捕捉我期望在未经授权的场景中看到的期望。 None 这些测试如我所愿地通过了:
// Does not work! I am expecting an error.
test("Unauthed subscriptions are rejected", done => {
const client = new TestClientApollo(process.env.TEST_HOST as string);
const sub = client.client.subscribe(defaultOptions).subscribe({
next(result) {
expect(result).toEqual({
data: {
counter: {
count: 0
}
}
});
sub.unsubscribe();
done();
}
});
// Received value must be a function, but instead "object" was found
expect(sub).toThrow();
});
// does not work
// Error: Uncaught { message: 'NO TOKEN PRESENT' }
test("Unauthed subscriptions are rejected second attempt", done => {
const client = new TestClientApollo(process.env.TEST_HOST as string);
try {
const sub = client.client.subscribe(defaultOptions).subscribe({
next(result) {
expect(result).toEqual({
data: {
counter: {
count: 0
}
}
});
sub.unsubscribe();
// done();
}
});
} catch (error) {
console.log(error);
expect(error).toEqual({
message: "NO TOKEN PRESENT"
});
done();
}
});
// does not work
// Error: Uncaught { message: 'NO TOKEN PRESENT' }
test("Unauthed subscriptions are rejected second attempt", done => {
const client = new TestClientApollo(process.env.TEST_HOST as string);
try {
const sub = client.client.subscribe(defaultOptions).subscribe({
next(result) {
expect(result).toEqual({
data: {
counter: {
count: 0
}
}
});
sub.unsubscribe();
// done();
}
});
} catch (error) {
console.log(error);
expect(error).toEqual({
message: "NO TOKEN PRESENT"
});
done();
}
});
// does not work
// Expected the function to throw an error.
// But it didn't throw anything.
test("Unauthed subscriptions are rejected third attempt", done => {
const client = new TestClientApollo(process.env.TEST_HOST as string);
expect(async () => {
const sub = await client.client.subscribe(defaultOptions).subscribe({
next(result) {
expect(result).toEqual({
data: {
counter: {
count: 0
}
}
});
sub.unsubscribe();
done();
}
});
}).toThrowError();
});
// does not work
// Expected the function to throw an error.
// But it didn't throw anything.
test("Unauthed subscriptions are rejected fourth attempt", done => {
const client = new TestClientApollo(process.env.TEST_HOST as string);
const attempt = async () => {
const sub = await client.client.subscribe(defaultOptions).subscribe({
next(result) {
expect(result).toEqual({
data: {
counter: {
count: 0
}
}
});
sub.unsubscribe();
done();
}
});
};
expect(attempt).toThrowError();
});
知道如何在未授权场景的测试中预期断言错误吗?
这里有完整的回购协议:https://github.com/jakelowen/typescript-graphql-boilerplate-server
嘘。我阅读了一般的可观察对象,特别是 observable.subscribe() 并发现第二个可选参数是一个 onError 回调函数。将测试重构为:
test("Unauthed subscriptions are rejected", done => {
const client = new TestClientApollo(process.env.TEST_HOST as string);
// jest.setTimeout(1000); // increase timeout
client.client.subscribe(defaultOptions).subscribe(
res => {
console.log(res);
},
err => {
expect(err).toEqual({ message: "NO TOKEN PRESENT" });
done();
}
);
});
并且一切都按预期工作。万岁!
边编:让我有点吃惊的是,经过几十个小时的google、堆栈溢出和github搜索,我从未找到一个简单、清晰的删除有关如何正确测试 graphql 订阅的教程。
我正在尝试使用 graphql-yoga 编写笑话测试来涵盖订阅。
我能够成功地测试快乐路径是订阅有效(使用授权)。不幸的是,我无法测试订阅 websocket 连接被拒绝的情况。
在我的服务器设置中,我拒绝任何未通过我的身份验证标准的 websocket 连接:
const app = await server.start({
cors,
port: process.env.NODE_ENV === "test" ? 0 : 4000,
subscriptions: {
path: "/",
onConnect: async (connectionParams: any) => {
const token = connectionParams.token;
if (!token) {
throw new AssertionError({ message: "NO TOKEN PRESENT" });
}
const decoded = parseToken(token, process.env.JWT_SECRET as string);
const user = await validateTokenVersion(decoded, redis);
if (user === {}) {
throw new AssertionError({ message: "NO VALID USER" });
}
return { user };
}
}
});
如我所愿,第一个测试(快乐之路)通过了:
// works as expected.
test("should start a subscription on network interface and unsubscribe", async done => {
const client = new TestClientApollo(process.env.TEST_HOST as string);
await client.register(email, password);
await User.update({ email }, { confirmed: true });
await client.login(email, password);
// set up subscription listener
const sub = client.client.subscribe(defaultOptions).subscribe({
next(result) {
expect(result).toEqual({
data: {
counter: {
count: 0
}
}
});
sub.unsubscribe();
done();
}
});
});
然后我尝试了 3 种不同的方法来捕捉我期望在未经授权的场景中看到的期望。 None 这些测试如我所愿地通过了:
// Does not work! I am expecting an error.
test("Unauthed subscriptions are rejected", done => {
const client = new TestClientApollo(process.env.TEST_HOST as string);
const sub = client.client.subscribe(defaultOptions).subscribe({
next(result) {
expect(result).toEqual({
data: {
counter: {
count: 0
}
}
});
sub.unsubscribe();
done();
}
});
// Received value must be a function, but instead "object" was found
expect(sub).toThrow();
});
// does not work
// Error: Uncaught { message: 'NO TOKEN PRESENT' }
test("Unauthed subscriptions are rejected second attempt", done => {
const client = new TestClientApollo(process.env.TEST_HOST as string);
try {
const sub = client.client.subscribe(defaultOptions).subscribe({
next(result) {
expect(result).toEqual({
data: {
counter: {
count: 0
}
}
});
sub.unsubscribe();
// done();
}
});
} catch (error) {
console.log(error);
expect(error).toEqual({
message: "NO TOKEN PRESENT"
});
done();
}
});
// does not work
// Error: Uncaught { message: 'NO TOKEN PRESENT' }
test("Unauthed subscriptions are rejected second attempt", done => {
const client = new TestClientApollo(process.env.TEST_HOST as string);
try {
const sub = client.client.subscribe(defaultOptions).subscribe({
next(result) {
expect(result).toEqual({
data: {
counter: {
count: 0
}
}
});
sub.unsubscribe();
// done();
}
});
} catch (error) {
console.log(error);
expect(error).toEqual({
message: "NO TOKEN PRESENT"
});
done();
}
});
// does not work
// Expected the function to throw an error.
// But it didn't throw anything.
test("Unauthed subscriptions are rejected third attempt", done => {
const client = new TestClientApollo(process.env.TEST_HOST as string);
expect(async () => {
const sub = await client.client.subscribe(defaultOptions).subscribe({
next(result) {
expect(result).toEqual({
data: {
counter: {
count: 0
}
}
});
sub.unsubscribe();
done();
}
});
}).toThrowError();
});
// does not work
// Expected the function to throw an error.
// But it didn't throw anything.
test("Unauthed subscriptions are rejected fourth attempt", done => {
const client = new TestClientApollo(process.env.TEST_HOST as string);
const attempt = async () => {
const sub = await client.client.subscribe(defaultOptions).subscribe({
next(result) {
expect(result).toEqual({
data: {
counter: {
count: 0
}
}
});
sub.unsubscribe();
done();
}
});
};
expect(attempt).toThrowError();
});
知道如何在未授权场景的测试中预期断言错误吗?
这里有完整的回购协议:https://github.com/jakelowen/typescript-graphql-boilerplate-server
嘘。我阅读了一般的可观察对象,特别是 observable.subscribe() 并发现第二个可选参数是一个 onError 回调函数。将测试重构为:
test("Unauthed subscriptions are rejected", done => {
const client = new TestClientApollo(process.env.TEST_HOST as string);
// jest.setTimeout(1000); // increase timeout
client.client.subscribe(defaultOptions).subscribe(
res => {
console.log(res);
},
err => {
expect(err).toEqual({ message: "NO TOKEN PRESENT" });
done();
}
);
});
并且一切都按预期工作。万岁!
边编:让我有点吃惊的是,经过几十个小时的google、堆栈溢出和github搜索,我从未找到一个简单、清晰的删除有关如何正确测试 graphql 订阅的教程。