rabbit_rabbit
rabbit_rabbit8mo ago

Leave TLS connection open in between tests

When I have 2 tests that use a database connection and attempt to close the connection afterAll the tests, the first fails because there's an open tls connection. Is it possible to leave the connection is open at the end of the first test?
import { afterAll, describe, it } from 'std/testing/bdd.ts'
import { assertEquals } from 'std/testing/asserts.ts'
import db from '../../db/db.ts'
import { sql } from "kysely"

describe('db/models/foo.ts', () => {
afterAll(() => db.destroy())

it('does something', async () => {
const result = await db.selectNoFrom(eb => [sql`1 + 1`.as('result')]).executeTakeFirst()
assertEquals(result, { result: 2 })
})

it('does something else', async () => {
const result = await db.selectNoFrom(eb => [sql`2 + 2`.as('result')]).executeTakeFirst()
assertEquals(result, { result: 4 })
})
})
import { afterAll, describe, it } from 'std/testing/bdd.ts'
import { assertEquals } from 'std/testing/asserts.ts'
import db from '../../db/db.ts'
import { sql } from "kysely"

describe('db/models/foo.ts', () => {
afterAll(() => db.destroy())

it('does something', async () => {
const result = await db.selectNoFrom(eb => [sql`1 + 1`.as('result')]).executeTakeFirst()
assertEquals(result, { result: 2 })
})

it('does something else', async () => {
const result = await db.selectNoFrom(eb => [sql`2 + 2`.as('result')]).executeTakeFirst()
assertEquals(result, { result: 4 })
})
})
results in
deno task test test/models/foo.test.ts
Task test DENO_TLS_CA_STORE=system IS_TEST=true deno test -A --unsafely-ignore-certificate-errors "test/models/foo.test.ts"
DANGER: TLS certificate validation is disabled for all hostnames
Check file:///Users/willweiss/dev/morehumaninternet/virtual-hospitals-africa/test/models/foo.test.ts
running 1 test from ./test/models/foo.test.ts
db/models/foo.ts ...
does something ... FAILED (21ms)
does something else ... ok (4ms)
db/models/foo.ts ... FAILED (due to 1 failed step) (31ms)

ERRORS

db/models/foo.ts ... does something => https://deno.land/std@0.190.0/testing/_test_suite.ts:323:15
error: Leaking resources:
- A TCP connection (rid 3) was opened/accepted during the test, but not closed during the test. Close the TCP connection by calling `tcpConn.close()`.

FAILURES

db/models/foo.ts ... does something => https://deno.land/std@0.190.0/testing/_test_suite.ts:323:15

FAILED | 0 passed (1 step) | 1 failed (1 step) (99ms)

error: Test failed
deno task test test/models/foo.test.ts
Task test DENO_TLS_CA_STORE=system IS_TEST=true deno test -A --unsafely-ignore-certificate-errors "test/models/foo.test.ts"
DANGER: TLS certificate validation is disabled for all hostnames
Check file:///Users/willweiss/dev/morehumaninternet/virtual-hospitals-africa/test/models/foo.test.ts
running 1 test from ./test/models/foo.test.ts
db/models/foo.ts ...
does something ... FAILED (21ms)
does something else ... ok (4ms)
db/models/foo.ts ... FAILED (due to 1 failed step) (31ms)

ERRORS

db/models/foo.ts ... does something => https://deno.land/std@0.190.0/testing/_test_suite.ts:323:15
error: Leaking resources:
- A TCP connection (rid 3) was opened/accepted during the test, but not closed during the test. Close the TCP connection by calling `tcpConn.close()`.

FAILURES

db/models/foo.ts ... does something => https://deno.land/std@0.190.0/testing/_test_suite.ts:323:15

FAILED | 0 passed (1 step) | 1 failed (1 step) (99ms)

error: Test failed
Thanks in advance!
2 Replies
Deno AI Helper
Deno AI Helper8mo ago
Based on the documentation, Deno's test runner includes a resource sanitizer that checks if all resources created during a test are closed before the test ends. This is to prevent resource leaks. By default, this sanitizer is enabled for all tests. In your case, the error message indicates that a TCP connection (which is used for the TLS connection to your database) was opened during the test but not closed. This is considered a resource leak, and Deno's test runner will fail the test because of it. If you want to keep the connection open between tests, you could disable the resource sanitizer for these tests by setting sanitizeResources: false in the test definition. However, this is generally not recommended because it could lead to actual resource leaks, especially if you forget to close the connection manually. Here's how you could modify your tests to disable the resource sanitizer:
describe('db/models/foo.ts', () => {
afterAll(() => db.destroy())

it('does something', async () => {
const result = await db.selectNoFrom(eb => [sql`1 + 1`.as('result')]).executeTakeFirst()
assertEquals(result, { result: 2 })
}, { sanitizeResources: false })

it('does something else', async () => {
const result = await db.selectNoFrom(eb => [sql`2 + 2`.as('result')]).executeTakeFirst()
assertEquals(result, { result: 4 })
}, { sanitizeResources: false })
})
describe('db/models/foo.ts', () => {
afterAll(() => db.destroy())

it('does something', async () => {
const result = await db.selectNoFrom(eb => [sql`1 + 1`.as('result')]).executeTakeFirst()
assertEquals(result, { result: 2 })
}, { sanitizeResources: false })

it('does something else', async () => {
const result = await db.selectNoFrom(eb => [sql`2 + 2`.as('result')]).executeTakeFirst()
assertEquals(result, { result: 4 })
}, { sanitizeResources: false })
})
However, a better approach would be to manage the database connection in a way that it gets closed after each test or after all tests have run. This way, you ensure that no resources are leaked and you don't need to disable the resource sanitizer. Please note that this information is not explicitly stated in the documentation, but is a general advice based on the principles of resource