I'm trying to write a unittest that will check if the correct error message is returned in case the database connection hits exception. I've tried to use connection.creation.destroy_test_db(':memory:') but it didn't work as I expected. I suppose I should either remove the tables or somehow cut the db connection. Is any of those possible?
-
1Maybe you can raise a DatabaseError and catch it. from django.db import DatabaseError raise DatabaseError Here the list of default django exceptions docs.djangoproject.com/en/dev/ref/exceptionsAzd325– Azd3252013-05-12 13:42:59 +00:00Commented May 12, 2013 at 13:42
-
I am confused. The question is titled "without connection", but in the body you said you are trying to assert the message is returned when there's an exception. Like what? Duplicate key? The title and the body don't quite match and I am just confused. Clarification?CppLearner– CppLearner2013-05-12 20:08:41 +00:00Commented May 12, 2013 at 20:08
-
1No connection to the database raises DatabaseError exception, which is what I'm trying to cause and assert the error message my webapp prints in this casetampakrap– tampakrap2013-06-08 19:18:23 +00:00Commented Jun 8, 2013 at 19:18
4 Answers
I found my answer in the presentation Testing and Django by Carl Meyer. Here is how I did it:
from django.db import DatabaseError
from django.test import TestCase
from django.test.client import Client
import mock
class NoDBTest(TestCase):
cursor_wrapper = mock.Mock()
cursor_wrapper.side_effect = DatabaseError
@mock.patch("django.db.backends.util.CursorWrapper", cursor_wrapper)
def test_no_database_connection(self):
response = self.client.post('/signup/', form_data)
self.assertEqual(message, 'An error occured with the DB')
Comments
Sounds like this is a job for mocking. For example, if you are using MySQL, you can put a side_effect on connect method, like this:
from django.test import TestCase
from mock import patch
import MySQLdb
class DBTestCase(TestCase):
def test_connection_error(self):
with patch.object(MySQLdb, 'connect') as connect_method:
connect_method.side_effect = Exception("Database Connection Error")
# your assertions here
Hope that helps.
1 Comment
Since dec, 2021 there is the library Django Mockingbird.
With this you can mock the object that would be retrieved from db.
from djangomockingbird import mock_model
@mock_model('myapp.myfile.MyModel')
def test_my_test():
some_test_query = MyModel.objects.filter(bar='bar').filter.(foo='foo').first()
#some more code
#assertions here
Comments
I was looking for django's actual http response code in case of a database connection timeout when using pymysql. The following test confirmed it's a 401 Unauthorized when pymysql raises an OperationalError.
from unittest.mock import patch
import pymysql
from django.test import TestCase, Client
class TestDatabaseOutage(TestCase):
client = None
def setUp(self):
self.client = Client()
def test_database_connection_timeout_returns_401(self):
with patch.object(pymysql, 'connect') as connect_method:
message = "Can't connect to MySQL server on 'some_database.example.com' ([Errno 110] Connection timed out)"
connect_method.side_effect = pymysql.OperationalError(2003, message)
response = self.client.get('/')
self.assertEqual(response.status_code, 401)