тестовые представления django, которые включают вызов сигнала - PullRequest
0 голосов
/ 22 октября 2018

У меня есть 2 приложения, одно для аутентификации и другое для хранения информации, связанной с профилем

приложение аутентификации models.py

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

signal.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: у пользователя нет профиля.

Однако я проверил создание пользователя и создание профиля впоследствии с помощью сигналов.Работает нормально.

1 Ответ

0 голосов
/ 22 октября 2018

Я вижу несколько проблем:

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...