tests.py 3.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. """Tests for django.db.utils."""
  2. import unittest
  3. from django.core.exceptions import ImproperlyConfigured
  4. from django.db import DEFAULT_DB_ALIAS, ProgrammingError, connection
  5. from django.db.utils import ConnectionHandler, load_backend
  6. from django.test import SimpleTestCase, TestCase
  7. from django.utils.connection import ConnectionDoesNotExist
  8. class ConnectionHandlerTests(SimpleTestCase):
  9. def test_connection_handler_no_databases(self):
  10. """
  11. Empty DATABASES and empty 'default' settings default to the dummy
  12. backend.
  13. """
  14. for DATABASES in (
  15. {}, # Empty DATABASES setting.
  16. {"default": {}}, # Empty 'default' database.
  17. ):
  18. with self.subTest(DATABASES=DATABASES):
  19. self.assertImproperlyConfigured(DATABASES)
  20. def assertImproperlyConfigured(self, DATABASES):
  21. conns = ConnectionHandler(DATABASES)
  22. self.assertEqual(
  23. conns[DEFAULT_DB_ALIAS].settings_dict["ENGINE"], "django.db.backends.dummy"
  24. )
  25. msg = (
  26. "settings.DATABASES is improperly configured. Please supply the "
  27. "ENGINE value. Check settings documentation for more details."
  28. )
  29. with self.assertRaisesMessage(ImproperlyConfigured, msg):
  30. conns[DEFAULT_DB_ALIAS].ensure_connection()
  31. def test_no_default_database(self):
  32. DATABASES = {"other": {}}
  33. conns = ConnectionHandler(DATABASES)
  34. msg = "You must define a 'default' database."
  35. with self.assertRaisesMessage(ImproperlyConfigured, msg):
  36. conns["other"].ensure_connection()
  37. def test_databases_property(self):
  38. # The "databases" property is maintained for backwards compatibility
  39. # with 3rd party packages. It should be an alias of the "settings"
  40. # property.
  41. conn = ConnectionHandler({})
  42. self.assertNotEqual(conn.settings, {})
  43. self.assertEqual(conn.settings, conn.databases)
  44. def test_nonexistent_alias(self):
  45. msg = "The connection 'nonexistent' doesn't exist."
  46. conns = ConnectionHandler(
  47. {
  48. DEFAULT_DB_ALIAS: {"ENGINE": "django.db.backends.dummy"},
  49. }
  50. )
  51. with self.assertRaisesMessage(ConnectionDoesNotExist, msg):
  52. conns["nonexistent"]
  53. class DatabaseErrorWrapperTests(TestCase):
  54. @unittest.skipUnless(connection.vendor == "postgresql", "PostgreSQL test")
  55. def test_reraising_backend_specific_database_exception(self):
  56. from django.db.backends.postgresql.psycopg_any import is_psycopg3
  57. with connection.cursor() as cursor:
  58. msg = 'table "X" does not exist'
  59. with self.assertRaisesMessage(ProgrammingError, msg) as cm:
  60. cursor.execute('DROP TABLE "X"')
  61. self.assertNotEqual(type(cm.exception), type(cm.exception.__cause__))
  62. self.assertIsNotNone(cm.exception.__cause__)
  63. if is_psycopg3:
  64. self.assertIsNotNone(cm.exception.__cause__.diag.sqlstate)
  65. self.assertIsNotNone(cm.exception.__cause__.diag.message_primary)
  66. else:
  67. self.assertIsNotNone(cm.exception.__cause__.pgcode)
  68. self.assertIsNotNone(cm.exception.__cause__.pgerror)
  69. class LoadBackendTests(SimpleTestCase):
  70. def test_load_backend_invalid_name(self):
  71. msg = (
  72. "'foo' isn't an available database backend or couldn't be "
  73. "imported. Check the above exception. To use one of the built-in "
  74. "backends, use 'django.db.backends.XXX', where XXX is one of:\n"
  75. " 'mysql', 'oracle', 'postgresql', 'sqlite3'"
  76. )
  77. with self.assertRaisesMessage(ImproperlyConfigured, msg) as cm:
  78. load_backend("foo")
  79. self.assertEqual(str(cm.exception.__cause__), "No module named 'foo'")