3 Réponses :
Si vous utilisez le APITestCase
de django, cela devient relativement simple.
class TestChangeEmail(APITestCase): def test_valid(self): user = UserFactory() auth_token = AuthToken.objects.create(user=user) response = self.client.post( reverse('your endpoint'), data={'email': 'foo@example.com'} ) self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertFalse(AuthToken.objects.filter(user=user).exists())
Cela évite de se moquer complètement et donne une représentation plus précise de votre logique.
Merci d'avoir écrit. Cependant, je souhaite tester sans utiliser la base de données. C'est pourquoi j'utilise mocker pour patcher les appels de base de données. Tel est le but de la question. J'utilise également un RequestFactory
au lieu du client
pour tester la vue directement. Je peux tester avec succès avec un accès db.
Voici un article de blog simple expliquant pourquoi écrire des tests unitaires sans accès à la base de données. chasse -seibert.github.io/blog/2012/07/27/…
Et voici une explication pour savoir pourquoi ne pas utiliser le client
. À votre santé. ianlewis.org/en/testing-django-views- sans-utiliser-test-clie nt
@pymarco citant le premier post que vous avez cité, À mon avis, se moquer de la couche de base de données est idiot; on a déjà une abstraction pour ça, ça s'appelle l'ORM. Au lieu de cela, vous pouvez obtenir toute la vitesse dont vous avez besoin en utilisant une base de données sqlite3 en mémoire pour vos tests unitaires. L'utilisation de RequestFactory
sur Client
est en effet logique dans certains scénarios (par exemple les tests de middleware), je n'ai jamais vu de cas d'utilisation qui nécessiterait de se moquer de la couche ORM.
@hoefling merci d'avoir signalé cette contradiction. J'allais vite et je l'ai négligé. Ma première pensée est préoccupante car Django propose de nombreuses fonctionnalités spécifiques à Postgres. Je vais maintenant considérer sqlite, mais je dois le faire avec prudence. Il ne semble pas idiot de se moquer de l'ORM, car je sais que l'ORM fonctionne, il est donc logique de contrôler sa sortie pendant un test.
Après avoir réfléchi un peu plus et lu pendant la dernière heure, je me sens plus confiant en testant avec Postgres si je vais utiliser l'accès à la base de données. Si la vitesse devient un problème au fur et à mesure que je me développe, je vais me réadresser. Autrement dit, à moins que quelqu'un ne puisse montrer comment patcher le RelatedManager
.
Vous devrez vous moquer de la valeur de retour de la fonction d'usine create_reverse_many_to_one_manager
. Exemple:
def test_valid(mocker): mgr = mocker.MagicMock() factory_orig = related_descriptors.create_reverse_many_to_one_manager def my_factory(superclass, rel): if rel.model == User and rel.name == 'auth_token_set': return mgr else: return factory_orig(superclass, rel) mocker.patch( 'django.db.models.fields.related_descriptors.create_reverse_many_to_one_manager', my_factory ) user = user_factory.build() user.id = 1 ... mgr.assert_called()
Attention, l'exemple ci-dessus se moquera du gestionnaire de rév pour tous les modèles. Si vous avez besoin d'une approche plus fine (par exemple, le gestionnaire de révision du correctif User.auth_token
uniquement, laissez le reste non corrigé), fournissez un implément d'usine personnalisé, par exemple
def test_valid(mocker): mgr = mocker.MagicMock() mocker.patch( 'django.db.models.fields.related_descriptors.create_reverse_many_to_one_manager', return_value=mgr ) user = user_factory.build() user.id = 1 ... mgr.assert_called()
Wow, c'est génial! Merci d'avoir compris cela
J'accomplis cela en faisant ceci (Django 1.11.5)
@patch("django.db.models.fields.related_descriptors.create_reverse_many_to_one_manager") def test_reverse_mock_count(self, reverse_mock): instance = mommy.make(DjangoModel) manager_mock = MagicMock count_mock = MagicMock() manager_mock.count = count_mock() reverse_mock.return_value = manager_mock instance.related_manager.count() self.assertTrue(count_mock.called)
espère cette aide!