Проблема с созданием модульных тестов для действий администратора Django
У меня есть небольшие проблемы с тем, чтобы понять, где нужно насмехаться и ставить заплатки, и это не имеет смысла для меня. Я создаю действие администратора, которое получает токен из стороннего API, а затем создает экземпляр локального класса (который подключается к этому API) и выполняет вызовы API на основе id элемента.
Например, предположим, что я храню рейтинги ресторанов во внешнем месте, доступном через вызовы API, а пользователей я храню локально. Я хочу создать действие администратора, которое будет проходить через каждого выбранного пользователя и удалять все рейтинги ресторанов во внешнем местоположении, которое аутентифицируется с помощью полученного токена. Я знаю, что это не оптимальный способ сделать вещи, но это явно не реальный пример, а просто аналог чего-то более сложного.
Вот структура моего проекта.
from external_class_location import ReviewClass # This is the class that hooks into the restaurant review location
from external_function_location import get_token # This is the method that fetches the token from that external location
class UserAdmin(admin.ModelAdmin)
actions = ['delete_reviews', ]
def delete_reviews(self, request, queryset):
reviews = ReviewClass(get_token())
for user in queryset:
reviews.delete_all_reviews(user)
delete_reviews.short_description = "Delete all reviews for selected users"
У меня есть набор тестов, настроенный следующим образом
import unittest
from unittest.mock import Mock, patch
from django.contrib.auth.models import User
from django.urls import reverse
from django.test import TestCase
class UserAdminTestCase(TestCase):
@patch('external_class_location.ReviewClass')
@patch('requests.post')
@patch('external_function_location.get_token')
def test_delete_reviews(self, mock_token, mock_requests_post, reviews_mock):
def setUp(self):
self.username = 'test_user'
self.password = 'test_password'
self.user = User.objects.create_superuser(self.username, 'test@example.com', self.password)
# the problem with this is that the requests.post method in the get_token method is being called even if I try to do this, which is why I had to create the MockRequest class below
mock_token.return_value = 'blah'
# This method works in that it returns the 'blah' token from requests.post but ultimately requests.post should never actually be called because I'm trying to mock the get_token method entirely
class MockRequest:
def __init__(self, token):
self.token = token
def json(self):
return dict(token=self.token)
mock_requests_post.return_value = MockRequest('blah')
sample_users = User.objects.all()[:10]
change_url = reverse('admin:app_model_changelist')
self.client.login(username=self.username, password=self.password)
self.client.post(change_url, dict(action='delete_reviews', _selected_action=sample_users), follow=True)
self.client.logout()
Я также застрял на последней части, где я просто хочу проверить, что метод delete_reviews
был вызван 10 раз. Я пытаюсь высмеять весь класс, но это не работает (в классе есть метод, который проверяет токен при инстанцировании, и, устанавливая его равным 'blah'
, он выдает ошибку), и более того, я не уверен, как высмеять метод внутри высмеиваемого класса, чтобы затем проверить, что этот высмеиваемый метод был вызван 10 раз
Я занимаюсь этим уже несколько часов, поэтому любая помощь будет искренне признательна.