1👍
While you can mock directly the ORM and return arbitrary results, I think it would be more efficient an insert fake data in the database using a library such as factory_boy and leave the ORM calls unmocked:
class EventFactory(factory.django.DjangoModelFactory):
class Meta:
model = 'myapp.Event'
class TestEventService(TestCase):
@classmethod
def setUpTestData(cls):
cls.event_service = EventService()
def test_get_all(self):
expected = [EventFactory() for i in range(10)]
self.assertListEqual(
self.event_service.get_all(),
expected)
At some point, you cannot mock everything, and if you mock ORM calls, you may end up with passing tests while your code is actually buggy (for example if you have a mistake in your filter
or exclude
statements.
If you can test it easily, and keep your test fast and efficient, I think you should avoid mocking something. In your case:
- You can easily create dummy data
- Your tests will still be fast if you use the ORM because Django by default uses an in-memory SQLite databse during tests, avoiding disk I/O.
Mocking would totally make sense in other situations though, such as retrieving data over the network using an HTTP API, for example.
1👍
In our project, we’re trying to decide when it’s a good idea to mock out the ORM layer and when it isn’t. Mocking the ORM layer makes the tests run way faster, but the tests are a bit more brittle.
To me, it seems like it’s not worth mocking the ORM if there’s any complexity in the queries. You should test complex queries against a test database with some sample data in it.
If you do have simple queries that you want to mock out, try the django-mock-queries package. I contributed a decorator called mocked_relations
that mocks out the stuff you’re asking about: Event.objects
and foreign key relations.
Take a look at the example that shows how to use it. You can list several model classes that you want to mock out.
@mocked_relations(User)
class TestMockedApi(TestCase):
def setUp(self):
self.api = AnalyticsApi()
def test_api_active_users_filters_by_is_active_true(self):
active_user = MockModel(mock_name='active user', is_active=True)
inactive_user = MockModel(mock_name='inactive user', is_active=False)
User.objects.add(*[active_user, inactive_user])
results = [x for x in self.api.active_users()]
assert active_user in results
assert inactive_user not in results
- [Answered ]-Setting a default value in choicfield in Django
- [Answered ]-Form validate like GenericView
- [Answered ]-How to POST with a field which is not specified in Form's Meta fields?