Question

I want to be able to do conditional connect() based on either I started django in testing mode or not.

in my settings.py I use mongoengine connect() method to connect to my database but the problem is that I don't want to do that if I ran manage.py test

Is there any way I can check if settings.py is being imported from tests or not, some flag maybe.

something like if not IN_TESTS: connect()

Was it helpful?

Solution

I'm solving this with a custom test runner. Here is an example I based my solution off of: https://github.com/xintron/django-mongorunner/blob/master/mongorunner/testrunner.py

This has the advantage of providing a fresh database for each of your unit tests.

class MyTestRunner(DjangoTestSuiteRunner):

    mongodb_name = 'testsuite'

    def setup_databases(self, **kwargs):
        from mongoengine.connection import connect, disconnect
        disconnect()
        connect(self.mongodb_name)
        print 'Creating mongo test-database ' + self.mongodb_name
        return super(MyTestRunner, self).setup_databases(**kwargs)

    def teardown_databases(self, old_config, **kwargs):
        from mongoengine.connection import get_connection, disconnect
        connection = get_connection()
        connection.drop_database(self.mongodb_name)
        print 'Dropping mongo test-database: ' + self.mongodb_name
        disconnect()
        super(MyTestRunner, self).teardown_databases(old_config, **kwargs)

OTHER TIPS

While it is possible to do that, it is easier and common practice to have 2 settings files. One possible configuration could be:

You have 2 settings files, lsettings.py that doesn't connect and settings.py that does

from lsettings import *
mongodb.connect()

So, while locally testing you can:

python manage.py test --settings=lsettings

And it doesn't connect.

tl;dr: It is easier to manage configuration differences by having multiple configuration files that import each other conditionally rather than trying to have conditional parameters within the same settings file. YMMV.

I'm not sure it's completely foolproof, but I use the fact that in a test, you will have probably started it from the command line with ./manage.py test, so 'test' is one of the command-line args. So this works:

import sys
if 'test' not in sys.argv:
    mongodb.connect()

What I do is use register_connection, and then mock the connections on test.

In the file that I define the Mongo Documents I have this:

import mongoengine
from django.conf import settings

mongoengine.register_connection(
    'default', settings.MONGOENGINE_DB, **settings.MONGOENGINE_CONNECTION)

Then in the tests I use the mock library to change the behave of connections (it would be possible too to mock one of the functions on the connection sub module like get_db) like this:

connections = patch.dict(
    mongoengine.connection._connections, {'default': None})

dbs = patch.dict(
    mongoengine.connection._dbs, {'default': {
        'your_collection': None,
        'another_collection': None,
        }})

dbs.start()
connections.start()

insert = patch.object(mongoengine.queryset.QuerySet, 'insert')
insert_mock = insert.start()

...

insert_mock.assert_called_once(...)
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top