【问题标题】:Django unit test - How to assert that a custom Manager calls the UserManager.create_user method?Django 单元测试 - 如何断言自定义管理器调用 UserManager.create_user 方法?
【发布时间】:2015-02-20 20:59:48
【问题描述】:

我是 Python 和 Django 中单元测试和模拟的新手。

这是我的模型(简化):

from django.db import models
from django.contrib.auth.models import User


class KangaUserManager(models.Manager):
    def create(self, username, email, password, last_name, first_name, request, registered=True, send_confirmation=True):
        kanga_user = KangaUser()
        kanga_user.user = User.objects.create_user(
            username=username,
            email=email,
            password=password,
            first_name=first_name,
            last_name=last_name
        )
        return kanga_user

class KangaUser(models.Model):
    objects = KangaUserManager()

    user = models.OneToOneField(User)

我想断言 User.objects.create_user 被调用,而不是实际调用它。我认为可以使用模拟库,但我什么也没做。

我试过这样的事情:

def test_create(self):
    with mock.patch('django.contrib.auth.models.UserManager') as usermanager_mock:
        kangauser_manager = KangaUserManager()
        kangauser_manager.create(self.username, self.email, self.password, self.last_name, self.first_name, self.request, self.registered, self.send_confirmation)

        self.assertTrue(usermanager_mock.create_user.called)

还有那个(还有很多我记不起来的事情:D)

def test_create(self):
    with mock.patch('django.contrib.auth.models.User') as user_mock:
        user_mock.objects = mock.MagicMock()
        user_mock.objects.create_user = mock.MagicMock()

        kangauser_manager = KangaUserManager()
        kangauser_manager.create(self.username, self.email, self.password, self.last_name, self.first_name, self.request, self.registered, self.send_confirmation)

        self.assertTrue(user_mock.objects.create_user.called)

但我总是看到没有调用该方法

我做错了什么?

(编辑 1:添加了一些导入)

编辑 2:

在进行 Alex martelli 建议的改编时,我偶然发现了另一个错误,

ValueError: Cannot assign "<MagicMock name='User.objects.create_user()' id='55229392'>": "KangaUser.user" must be a "User" instance.

这是修改后的代码:

from django.db import models
from django.contrib.auth import models as auth_model


class KangaUserManager(models.Manager):
    def create(self, username, email, password, last_name, first_name, request, registered=True, send_confirmation=True):
        kanga_user = KangaUser()
        kanga_user.user = auth_model.User.objects.create_user(
            username=username,
            email=email,
            password=password,
            first_name=first_name,
            last_name=last_name
        )
        return kanga_user

class KangaUser(models.Model):
    objects = KangaUserManager()

    user = models.OneToOneField(auth_model.User)

【问题讨论】:

  • 您是 models.Manager 的子类,但调用 Users.something 而不是 models.User.something。这表明您的测试代码已经直接导入了User 以及models,并且模拟直接导入的类(可以做到但)更难。你能改变你的测试代码来调用models.User吗?否则,您将不得不模拟 User 在您的测试代码中,而不是在 django 包层次结构中(一个典型的模拟问题,顺便说一句)。
  • 我可以试试,但是问题(我没有把它放在我展示的代码中,我应该编辑它以使其更清楚,这是模型来自不同的模块,来自 django .db import models from django.contrib.auth.models import User 我将尝试使用别名进行导入。感谢您的回答

标签: python django unit-testing mocking


【解决方案1】:

使用 MagicMock 时需要返回一个值。

from unittest.mock import MagicMock

thing = KangaUserManager()
thing.create_user = MagicMock(return_value=True)
self.assertTrue(thing.create_user(**user_kwargs))

【讨论】:

    【解决方案2】:

    好的,感谢 Alex 和 Aaron,我得到了所需的线索,让它按我想要的方式工作,谢谢!

    所以,这里是代码

    from django.db import models
    from django.contrib.auth import models as auth_model
    
    
    class KangaUserManager(models.Manager):
        def create(self, username, email, password, last_name, first_name, request, registered=True, send_confirmation=True):
            kanga_user = KangaUser()
            kanga_user.user = auth_model.User.objects.create_user(
                username=username,
                email=email,
                password=password,
                first_name=first_name,
                last_name=last_name
            )
            return kanga_user
    
    class KangaUser(models.Model):
        objects = KangaUserManager()
    
        user = models.OneToOneField(auth_model.User)
    

    以及有效的测试:

    def test_create(self):
        with mock.patch('django.contrib.auth.models.User') as user_mock:
            user_mock.objects = mock.MagicMock()
            user_mock.objects.create_user = mock.MagicMock()
            user_mock.objects.create_user.return_value = User()
    
            kangauser_manager = KangaUserManager()
            kangauser_manager.create(self.username, self.email, self.password, self.last_name, self.first_name, self.request, self.registered, self.send_confirmation)
    
            self.assertTrue(user_mock.objects.create_user.called)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-15
      • 2014-11-14
      • 2013-03-18
      • 2011-04-19
      相关资源
      最近更新 更多