【问题标题】:django test views that involve invocation of a signal涉及调用信号的 django 测试视图
【发布时间】:2018-10-22 03:20:04
【问题描述】:

我有 2 个应用程序,1 个用于身份验证,另一个用于存储个人资料相关信息

身份验证应用 models.py

class User(AbstractUser):
      # contains the User related info

signals.py

@receiver(post_save, sender=User)
def create_related_profile(sender, instance, created, *args, **kwargs):
if instance and created:
    instance.profile = Profile.objects.create(user=instance)

个人资料应用 models.py

class Profile(models.Model):
    user = models.OneToOneField(User)
    # other info

在测试更新用户方法时。

class TestUserRetrieveUpdateView(APITestCase):
def setUp(self):
    self.test_username = 'testuser'
    self.test_email = 'test@example.com'
    self.test_password = 'testpassword'
    # We want to go ahead and originally create a user.
    self.test_user = get_user_model().objects.create_user(self.test_username,
                                                          self.test_email, self.test_password)

    self.auth_headers = {'HTTP_AUTHORIZATION': f"Bearer {self.test_user.token}"}
    # URL for creating an account.
    self.detail_url = reverse('users:detail')

    # URL for creating an account.
    self.create_url = reverse('users:signup')

    # Request factory
    self.request_factory = RequestFactory()

@patch('yapoll.users.signals.create_related_profile')
def test_udpate_user_with_preexisting_username(self, mock):

    data_1 = {
        'username': 'testuser2',
        'email': 'test_1@example.com',
        'password': 'testuser'
    }

    response_1 = self.client.post(self.create_url, data_1, format='json')
    data = {'username': 'testuser2'}
    # TODO: Complete this test case handling signals
    response = self.client.put(self.detail_url, data, format='json', **self.auth_headers)
    self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
    self.assertEqual(get_user_model().objects.count(), 2)
    self.assertTrue('errors' in response.data)
    self.assertTrue('username' in response.data['errors'])
    self.assertEqual(len(response.data['errors']['username']), 1)

在执行此操作时,我收到以下错误。 django.db.models.fields.related_descriptors.RelatedObjectDoesNotExist:用户没有个人资料。

但是,我随后使用信号测试了用户创建和配置文件创建。它工作正常。

【问题讨论】:

  • 您必须为您的用户创建一个 Profile 实例。
  • 我应该明确地这样做吗?在创建用户时,信号应该调用配置文件的创建吗?请检查前几行 auth app 部分的 signals.py 中的 post_save 信号。如果我错了,请纠正我

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


【解决方案1】:

我发现了一些问题:

1.你的接收者没有在实例上调用保存,所以在你分配instance.profile之后它不会将这些更改保存到数据库中。

@receiver(post_save, sender=User)
def create_related_profile(sender, instance, created, *args, **kwargs):
    if instance and created:
        instance.profile = Profile.objects.create(user=instance)
        instance.save()

2.另一个潜在问题可能是您在测试中创建用户并将其分配给test_user。当您调用create_user 时,它会返回保存时的实例,该实例没有分配配置文件,因为配置文件是在接收器中创建后分配的。您可以使用self.test_user.refresh_from_db() 使用数据库中的任何新数据更新实例,在这种情况下,它将检索在您的 post_save 信号中添加到实例的配置文件。

self.test_user = get_user_model().objects.create_user(
    self.test_username,
    self.test_email, 
    self.test_password
)
#  print(self.test_user.profile)  # this would fail or print None
self.test_user.refresh_from_db()
#  print(self.test_user.profile)  # Now this should print the profile object

【讨论】:

  • 我在尝试使用不同的用户名更新用户时没有得到这个,同时调用这个方法 - response = self.client.put(self.detail_url, data, format='json', * *self.auth_headers)。这是一个 HTTP 请求。但是,我认为它甚至在创建操作完成之前就被调用了。
猜你喜欢
  • 2018-05-16
  • 2016-12-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多