Test case is leaking async ops on deno

Viewed 1068

I downloaded the example app from Drash (https://github.com/drashland/deno-drash)

$ deno run --allow-run --allow-read --allow-write --allow-net https://deno.land/x/drash/create_app.ts --api

and try to add a new test, which:

  1. will fetch GET /
  2. Assert status code and response json
Deno.test("HomeResource - GET /", async () => {
  const response = await fetch("http://localhost:1557", {
    method: "GET",
  });
  assertEquals(response.status, 200);
  assertEquals(
    await response.json(),
    JSON.stringify({
      success: true,
      message: "GET request received.",
    }),
  );
});

Here is the error message

Server listening: http://localhost:1557
running 5 tests
test HomeResource - GET / ... FAILED (9ms)
test HomeResource - POST / ... ok (2ms)
test HomeResource - PUT / ... ok (2ms)
test HomeResource - DELETE / ... ok (2ms)

Stop the server ... ok (0ms)

failures:

HomeResource - GET /
AssertionError: Test case is leaking async ops.
Before:
  - dispatched: 1
  - completed: 0
After:
  - dispatched: 9
  - completed: 7

Make sure to await all promises returned from Deno APIs before
finishing test case.
    at assert (rt/06_util.js:33:13)
    at asyncOpSanitizer (rt/40_testing.js:44:7)
    at async Object.resourceSanitizer [as fn] (rt/40_testing.js:68:7)
    at async TestRunner.[Symbol.asyncIterator] (rt/40_testing.js:240:13)
    at async Object.runTests (rt/40_testing.js:317:22)

failures:

    HomeResource - GET /

test result: FAILED. 4 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out (15ms)

I have tried to cancel the body with response.body?.cancel(), but says that the stream is locked.

Tests: https://github.com/ramonmedeiros/learning_deno/blob/master/tests/resources/home_resource_test.ts

1 Answers

The test cases are leaking ops and resources. Maybe Drash is not handling this properly.

These are the resources before and after the fetch request-

┌───────┬───────────────┐
│ (idx) │    Values     │
├───────┼───────────────┤
│   0   │    "stdin"    │
│   1   │   "stdout"    │
│   2   │   "stderr"    │
│   3   │ "tcpListener" │
└───────┴───────────────┘
┌───────┬───────────────┐
│ (idx) │    Values     │
├───────┼───────────────┤
│   0   │    "stdin"    │
│   1   │   "stdout"    │
│   2   │   "stderr"    │
│   3   │ "tcpListener" │
│   4   │  "tcpStream"  │
└───────┴───────────────┘

These are the ops before and after the fetch request-

┌─────────────────────────┬────────┐
│          (idx)          │ Values │
├─────────────────────────┼────────┤
│      opsDispatched      │   5    │
│    opsDispatchedSync    │   4    │
│   opsDispatchedAsync    │   1    │
│ opsDispatchedAsyncUnref │   0    │
│      opsCompleted       │   4    │
│    opsCompletedSync     │   4    │
│    opsCompletedAsync    │   0    │
│ opsCompletedAsyncUnref  │   0    │
│    bytesSentControl     │  121   │
│      bytesSentData      │   46   │
│      bytesReceived      │  418   │
└─────────────────────────┴────────┘
┌─────────────────────────┬────────┐
│          (idx)          │ Values │
├─────────────────────────┼────────┤
│      opsDispatched      │   14   │
│    opsDispatchedSync    │   6    │
│   opsDispatchedAsync    │   8    │
│ opsDispatchedAsyncUnref │   0    │
│      opsCompleted       │   12   │
│    opsCompletedSync     │   6    │
│    opsCompletedAsync    │   6    │
│ opsCompletedAsyncUnref  │   0    │
│    bytesSentControl     │  323   │
│      bytesSentData      │ 73903  │
│      bytesReceived      │  1060  │
└─────────────────────────┴────────┘

The tcpStream resource is not closed after the test. See the opsDispatchedAsync and opsCompletedAsync. All the async ops are not completed. This is async ops and resources sanitization as mentioned here. These are enabled by default but can be disabled by setting sanitizeResources and sanitizeOps to false as done in the last test case -

Deno.test({
  name: "\b\b\b\b\b     \nStop the server",
  fn() {
    server.close();
  },
  sanitizeResources: false,
  sanitizeOps: false,
});
Related