web-dev-qa-db-fra.com

Comment se moquer d'un objet modèle Django (avec ses méthodes)?

J'essaie de me moquer d'un objet de modèle chaîné Django dans la méthode factice suivante,

# utils.py
def foo_something_exist():
   if Foo.objects.get(a='something').exist():
      return 'exist'



# test.py
import unittest.mock import patch

import utils

.
.
.
@patch('utils.Foo')
def test_foo_something_exist_returns_none(self, mock_foo):
   mock_foo.objects.get.exists.return_value = False
   self.assertIsNone(utils.foo_something_exist()) 
.
.
.

test_foo_something_exist() échoue au test. J'ai découvert que Foo.objects.get(a='something').exist() dans utils.py était un objet MagicMock (<MagicMock name='Member.objects.get().exists()' id='xxxxxx'>) au lieu de False, ce qui a contribué à l'échec de cette fonction de test. Et oui, j'ai aussi essayé mock_foo.objects.return_value.get.return_value.exists.return_value = False, Qui a été mentionné dans un post. Des pointeurs/astuces pour se moquer correctement d'un objet modèle (avec ses méthodes chaînées) sont appréciés.

Merci d'avance.

11
tebesfinwo

Ne patchez pas le modèle lui-même, mais model.objects, puis moquez chaque partie de la chaîne:

@patch('utils.Foo.objects')
def test_foo_something_exist_returns_none(self, mock_foo):
    # just to show how to do it with longer chains
    # mock_foo.filter.return_value = mock_foo
    # mock_foo.exclude.return_value = mock_foo            
    mock_foo.get.return_value = mock_foo
    mock_foo.exists.return_value = False

    self.assertIsNone(utils.foo_something_exist()) 

Cela fonctionne également avec .filter(), .exclude() et d'autres opérations de modèle. Je trouve également Model Mommy vraiment utile pour tester les modèles Django.

14
masterfloda