簡體   English   中英

如何在Jest / Apollo客戶端中捕獲拒絕的graphql訂閱?

[英]How to catch rejected graphql subscription in jest / apollo client?

我正在嘗試使用graphql-yoga編寫玩笑測試來涵蓋訂閱。

我能夠成功地測試訂閱模式(使用auth)的快樂路徑。 不幸的是,我無法測試預訂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 };
      }
    }
  });

https://github.com/jakelowen/typescript-graphql-boilerplate-server/blob/master/src/startServer.ts#L87

現在在我的相關測試中: https : //github.com/jakelowen/typescript-graphql-boilerplate-server/blob/master/src/modules/counter/counter.test.ts

我希望通過第一個測試(幸福的道路):

// 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種不同的方式來捕捉我希望在未認證的場景中看到的期望。 這些測試都沒有通過,正如我希望的那樣:

// 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

布阿 我閱讀了一般的observables,特別是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訂閱的簡單明了的教程,這讓我感到驚訝。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM