mirror of
https://github.com/suitenumerique/docs.git
synced 2026-10-01 22:15:14 +02:00
🐛(backend) close thread DB connections to fix test teardown OperationalError
When all the tests are ran, there is a PytestWarning log present to warn us that there is remaining database connection open and can not be closed. It appears that the tests about concurrence are responsible of leaving connection open. We need to manually close them in these tests.
This commit is contained in:
@@ -6,6 +6,11 @@ and this project adheres to
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
### Fixed
|
||||
|
||||
- 🐛(backend) close thread DB connections to fix test teardown
|
||||
OperationalError #2385
|
||||
|
||||
## [v5.2.0] - 2026-06-03
|
||||
|
||||
### Added
|
||||
|
||||
@@ -8,6 +8,8 @@ from unittest import mock
|
||||
from unittest.mock import patch
|
||||
from uuid import uuid4
|
||||
|
||||
from django.db import connection
|
||||
|
||||
import pytest
|
||||
from rest_framework.test import APIClient
|
||||
|
||||
@@ -286,12 +288,17 @@ def test_api_documents_create_document_children_race_condition():
|
||||
factories.UserDocumentAccessFactory(user=user, document=document, role="owner")
|
||||
|
||||
def create_document():
|
||||
return client.post(
|
||||
f"/api/v1.0/documents/{document.id}/children/",
|
||||
{
|
||||
"title": "my child",
|
||||
},
|
||||
)
|
||||
try:
|
||||
return client.post(
|
||||
f"/api/v1.0/documents/{document.id}/children/",
|
||||
{
|
||||
"title": "my child",
|
||||
},
|
||||
)
|
||||
finally:
|
||||
# Close this worker thread's thread-local database connection so it
|
||||
# does not linger and block dropping the test database at teardown.
|
||||
connection.close()
|
||||
|
||||
with ThreadPoolExecutor(max_workers=2) as executor:
|
||||
future1 = executor.submit(create_document)
|
||||
|
||||
@@ -6,6 +6,8 @@ from concurrent.futures import ThreadPoolExecutor
|
||||
from unittest import mock
|
||||
from uuid import uuid4
|
||||
|
||||
from django.db import connection
|
||||
|
||||
import pytest
|
||||
from rest_framework.test import APIClient
|
||||
|
||||
@@ -70,16 +72,21 @@ def test_api_documents_create_document_race_condition():
|
||||
"""
|
||||
|
||||
def create_document(title):
|
||||
user = factories.UserFactory()
|
||||
client = APIClient()
|
||||
client.force_login(user)
|
||||
return client.post(
|
||||
"/api/v1.0/documents/",
|
||||
{
|
||||
"title": title,
|
||||
},
|
||||
format="json",
|
||||
)
|
||||
try:
|
||||
user = factories.UserFactory()
|
||||
client = APIClient()
|
||||
client.force_login(user)
|
||||
return client.post(
|
||||
"/api/v1.0/documents/",
|
||||
{
|
||||
"title": title,
|
||||
},
|
||||
format="json",
|
||||
)
|
||||
finally:
|
||||
# Close this worker thread's thread-local database connection so it
|
||||
# does not linger and block dropping the test database at teardown.
|
||||
connection.close()
|
||||
|
||||
with ThreadPoolExecutor(max_workers=2) as executor:
|
||||
future1 = executor.submit(create_document, "my document 1")
|
||||
|
||||
@@ -9,6 +9,7 @@ from unittest import mock
|
||||
from unittest.mock import patch
|
||||
|
||||
from django.core import mail
|
||||
from django.db import connection
|
||||
from django.test import override_settings
|
||||
|
||||
import pytest
|
||||
@@ -480,16 +481,21 @@ def test_api_documents_create_document_race_condition():
|
||||
"""
|
||||
|
||||
def create_document(title):
|
||||
user = factories.UserFactory()
|
||||
client = APIClient()
|
||||
client.force_login(user)
|
||||
return client.post(
|
||||
"/api/v1.0/documents/",
|
||||
{
|
||||
"title": title,
|
||||
},
|
||||
format="json",
|
||||
)
|
||||
try:
|
||||
user = factories.UserFactory()
|
||||
client = APIClient()
|
||||
client.force_login(user)
|
||||
return client.post(
|
||||
"/api/v1.0/documents/",
|
||||
{
|
||||
"title": title,
|
||||
},
|
||||
format="json",
|
||||
)
|
||||
finally:
|
||||
# Close this worker thread's thread-local database connection so it
|
||||
# does not linger and block dropping the test database at teardown.
|
||||
connection.close()
|
||||
|
||||
with ThreadPoolExecutor(max_workers=2) as executor:
|
||||
future1 = executor.submit(create_document, "my document 1")
|
||||
|
||||
@@ -7,6 +7,7 @@ from concurrent.futures import ThreadPoolExecutor
|
||||
from unittest.mock import patch
|
||||
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.db import connection
|
||||
from django.test.utils import override_settings
|
||||
|
||||
import pytest
|
||||
@@ -341,7 +342,14 @@ def test_models_users_duplicate_onboarding_sandbox_race_condition():
|
||||
"""
|
||||
|
||||
def create_user():
|
||||
return factories.UserFactory()
|
||||
try:
|
||||
return factories.UserFactory()
|
||||
finally:
|
||||
# Each worker thread gets its own thread-local database connection.
|
||||
# Close it explicitly so it does not linger and block dropping the
|
||||
# test database during teardown (OperationalError: "database is being
|
||||
# accessed by other users").
|
||||
connection.close()
|
||||
|
||||
template_document = factories.DocumentFactory(title="Getting started with Docs")
|
||||
with (
|
||||
|
||||
Reference in New Issue
Block a user