【问题标题】:AttributeError: <bound method Manager.get of <django.db.models.manager.ManagerAttributeError: <django.db.models.manager.Manager 的 <bound method Manager.get
【发布时间】:2017-11-23 16:18:44
【问题描述】:

我在单元测试方面没有进行太多实验,我收到以下错误并且我无法修复,我将不胜感激。谢谢

这是返回的错误:

    ======================================================================
ERROR: test_authenticate_credentials_for_inactive_user (apps.authentication.tests.test_authentication.AuthenticateCredentialsTest)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/usr/local/site-packages/mock/mock.py", line 1297, in patched
    arg = patching.__enter__()
  File "/usr/local/site-packages/mock/mock.py", line 1369, in __enter__
    original, local = self.get_original()
  File "/usr/local/site-packages/mock/mock.py", line 1343, in get_original
    "%s does not have the attribute %r" % (target, name)
AttributeError: <bound method Manager.get of <django.db.models.manager.Manager object at 0x00000000015bd168>> does not have the attribute 'has_expired'

这是代码:

class ExpiringTokenAuthentication(TokenAuthentication):
    """
    Extends token auth with inactivity expiration mechanism.
    """
    model = ExpiringToken

    def authenticate_credentials(self, key):

        try:
            token = self.model.objects.get(key=key)
        except self.model.DoesNotExist:
            raise exceptions.AuthenticationFailed('Invalid token')

        if not token.user.is_active:
            raise exceptions.AuthenticationFailed('Invalid user')

        if token.has_expired():
            raise exceptions.AuthenticationFailed('Token has expired')

单元测试:

class AuthenticateCredentialsTest(TestCase):

    def setUp(self):
        self.ExpiringTokenAuth = ExpiringTokenAuthentication()


    @patch('apps.authentication.authentication.ExpiringTokenAuthentication.model.objects.get')
    @patch('apps.authentication.authentication.ExpiringTokenAuthentication.model.objects.get.user.is_active')
    @patch('apps.authentication.authentication.ExpiringTokenAuthentication.model.objects.get.has_expired')
    def test_authenticate_credentials_for_inactive_user(self, mock_token, active_user, expired_token):
        active_user.return_value = True
        expired_token.return_value = False
        with self.assertRaises(exceptions.AuthenticationFailed) as ea:
            self.ExpiringTokenAuth.authenticate_credentials('valid key')

【问题讨论】:

    标签: python django unit-testing django-rest-framework


    【解决方案1】:

    问题是:你试图通过.get() 方法返回一个对象,这不是它的工作原理。您需要自己修补实例:

    @patch('apps.authentication.authentication.ExpiringTokenAuthentication.model.objects.get')
    @patch('apps.authentication.authentication.token.user.is_active')
    @patch('apps.authentication.authentication.token.has_expired')
    def test_authenticate_credentials_for_inactive_user(self, mock_token, active_user, expired_token):
        active_user.return_value = True
        expired_token.return_value = False
        with self.assertRaises(exceptions.AuthenticationFailed) as ea:
            self.ExpiringTokenAuth.authenticate_credentials('valid key')
    

    【讨论】:

    • 我现在收到此错误:ImportError: No module named apps.authentication.authentication.ExpiringTokenAuthentication
    • 在第一个补丁中试试这个@patch('apps.authentication.authentication.ExpiringTokenAuthentication.model.objects.get', autospec=True)
    • 仍然有同样的错误。我想知道是否有更简单的方法可以做到这一点?
    • 是的,在测试中,您可以在数据库中创建一个带有非活动用户的令牌,然后是其他已过期的令牌,以及其他使用不存在的密钥的测试
    • 正如我在问题中所说,我对单元测试不是很有经验,所以如果您能告诉我如何使用非活动用户创建令牌,我将不胜感激,其余的我会自己做.谢谢
    【解决方案2】:

    您可以在不同的测试中将每个案例分开。例如:

    class AuthenticateCredentialsTest(TestCase):
    
    def setUp(self):
        self.ExpiringTokenAuth = ExpiringTokenAuthentication()
        self.token = ExpiringToken.objects.create(key="valid_key")
    
    def tearDown(self):
        del self.ExpiringTokenAuth
        del self.token
    
    def test_for_non_existent_token(self):
        with self.assertRaises(exceptions.AuthenticationFailed) as ea:
            self.ExpiringTokenAuth.authenticate_credentials('invalid_key')
    
    def test_for_user_inactive(self):
        user = <UserModel>.objects.create(is_active=False, **params)  # Create your own inactive user
        self.token.user = user
        self.token.save()
    
        with self.assertRaises(exceptions.AuthenticationFailed) as ea:
            self.ExpiringTokenAuth.authenticate_credentials('valid_key')
    
    def test_for_has_expired(self):
        self.token.expired = True  # Make the method has_expired return True
        self.token.save()
    
        with self.assertRaises(exceptions.AuthenticationFailed) as ea:
            self.ExpiringTokenAuth.authenticate_credentials('valid_key')
    

    【讨论】:

      猜你喜欢
      • 2015-05-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-10-17
      • 1970-01-01
      相关资源
      最近更新 更多