Skip to content

Instantly share code, notes, and snippets.

@pandichef
Created August 13, 2020 06:02
Show Gist options
  • Save pandichef/d3cc137036a7be0c29e9afb27bfbf55e to your computer and use it in GitHub Desktop.
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
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