lundi 4 novembre 2019

How can I mock a ManyToMany Field?

I have these models to test:

#models.py (simplified, name is a costum multilanguage field)
class NameType(models.Model):
    name = models.CharField(_('nome'), max_length=25, unique=True)

class NameLanguage(models.Model):
    name = models.CharField(_('nome'), max_length=25, unique=True)
    syntax = models.ManyToManyField(
        NameType, related_name='syntax_name',
        verbose_name=_('sintassi'))

To isolate the tests I want to use mock() (I already tested NameType)

#test_models.py
class NameLanguageTest(TestCase):
    def test_language_created(self):
        self.name = Mock(spec=NameType)
        self.surname = Mock(spec=NameType)
        self.romans = NameLanguage.objects.create(name='Romans')
        self.romans.syntax.add(self.name)
        self.romans.syntax.add(self.surname)
        self.assertEqual(NameLanguage.objects.all().count(), 1)
        self.assertEqual(
            list(NameLanguage.objects.get(name='romans').syntax.all()),
            [name, surname]
        )

but when I try to add name and surname to M2M syntax it gives me this error:

Traceback (most recent call last):
  File "E:\progetti\ElencoNomi\lists\tests\test_models.py", line 79, in test_language_created
    self.romani.syntax.add(nome)
  File "e:\progetti\envs\ElencoNomi\lib\site-packages\django\db\models\fields\related_descriptors.py", line 938, in add
    through_defaults=through_defaults,
  File "e:\progetti\envs\ElencoNomi\lib\site-packages\django\db\models\fields\related_descriptors.py", line 1039, in _add_items
    if not router.allow_relation(obj, self.instance):
  File "e:\progetti\envs\ElencoNomi\lib\site-packages\django\db\utils.py", line
280, in allow_relation
    return obj1._state.db == obj2._state.db
  File "E:\Python\Python37\lib\unittest\mock.py", line 593, in __getattr__
    raise AttributeError("Mock object has no attribute %r" % name)
AttributeError: Mock object has no attribute '_state'

Also should I use self.name and self.surname (like I did in the code above) or just name and surname? There is difference?

Thank you

Aucun commentaire:

Enregistrer un commentaire