-
-
Save pandichef/d3cc137036a7be0c29e9afb27bfbf55e to your computer and use it in GitHub Desktop.
3 ways to mock a Django model that is passed into a function as a parameter
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import json | |
from django.db.models import Model | |
from typing import Type | |
from unittest.mock import MagicMock | |
from types import SimpleNamespace | |
from collections import namedtuple | |
def get_list_of_field_names(DjangoModel: Type[Model]) -> list: | |
return list(map(lambda x: x.name, DjangoModel._meta.fields)) | |
def test_using_magicmock(): | |
MockedDjangoModel = MagicMock(name="MockedDjangoModel") | |
field0 = MagicMock() | |
field0.name = "field0" | |
field1 = MagicMock() | |
field1.name = "field1" | |
MockedDjangoModel._meta.fields = (field0, field1) | |
assert get_list_of_field_names(MockedDjangoModel) == ["field0", "field1"] | |
def test_using_simplenamespace(): | |
"""This is a trick to get a similar result using SimpleNamespace. Since it uses | |
json.dumps, it only works for JSON serializable dictionary values. If the dictionary | |
contains a Python object, this will throw: | |
TypeError: Object of type type is not JSON serializable | |
Ref: https://docs.python.org/3/library/json.html#json.load | |
""" | |
# Ref: https://stackoverflow.com/questions/50490856/creating-a-namespace-with-a-dict-of-dicts | |
d = {"_meta": {"fields": ({"name": "field0"}, {"name": "field1"})}} | |
MockedDjangoModel = json.loads( | |
json.dumps(d), object_hook=lambda d: SimpleNamespace(**d) | |
) | |
assert get_list_of_field_names(MockedDjangoModel) == ["field0", "field1"] | |
def test_using_namedtuple(): | |
"""In theory this could work too, but named tuple field names cannot start with an | |
underscore for whatever reason | |
Ref: https://docs.python.org/3/library/collections.html#collections.namedtuple | |
""" | |
d = {"_meta": {"fields": ({"name": "field0"}, {"name": "field1"})}} | |
try: | |
MockedDjangoModel = json.loads( | |
json.dumps(d), | |
object_hook=lambda d: namedtuple( | |
"MockedDjangoModel", d.keys(), defaults=d.values(), | |
)(), | |
) | |
assert get_list_of_field_names(MockedDjangoModel) == ["field0", "field1"] | |
except ValueError as e: | |
print(repr(e)) # Field names cannot start with an underscore: '_meta' |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment