首页 > 解决方案 > Django 测试客户端发布请求重定向失败

问题描述

当我发出发布请求而不是使用状态码 302 重定向时,我的 django.test 客户端返回状态码为 200 的响应。

我将 Django 2.2.4 与 Python 3.7.3 一起使用。

不需要登录(如Why does Django Redirect Test Fail?所述),也不需要将 follow 和 secure 参数设置为 True(如Django 测试客户端 POST 命令未通过 301 重定向注册

我注意到同样的问题影响了我的更新视图。当我使用 put 方法调用 Django 测试客户端时,它不会重定向。(我没有包含此代码以避免冗长)。

最后,我注意到页面重定向在我python manage.py runserver访问页面以创建新的 Book 实例时起作用。

这是测试:

from django.test import TestCase, Client
from django.urls import reverse
...

class TestDashboardViews(TestCase):
    def setUp(self):
        self.client = Client()
        self.book_list_url = reverse("dashboard-home")
        self.book_create_url = reverse("dashboard-upload-book")
        self.another_demo_book_kwargs = {
            "title": "Demo Title",
            "author": "Demo Author",
            "subject": "Another Demo Subject",
            "details": "Another Demo Details",
            "file": "path/to/another/demo/file"
        }
        ...

    def test_book_create_view_using_post_method(self):
        response = self.client.post(self.book_create_url, self.another_demo_book_kwargs)

        self.assertRedirects(response, self.book_list_url)
        ...

这是受影响的视图:

class BookCreateView(CreateView):
    model = Book
    fields = ['title', 'author', 'subject', 'details', 'file']
    success_url = reverse_lazy("dashboard-home")

这是模型:

from django.db import models
from django.utils.text import slugify


class Book(models.Model):
    title = models.CharField(max_length=50)
    slug = models.SlugField()
    author = models.CharField(max_length=100)
    subject = models.CharField(max_length=50)
    details = models.CharField(max_length=255)

    def author_title_path(self, filename):
        return "files/{author}/{filename}".format(author=slugify(self.author), filename=filename)

    file = models.FileField(upload_to=author_title_path)

    def save(self, *args, **kwargs):
        title_by_author = "{title} by {author}".format(title=self.title, author=self.author)
        self.slug = slugify(title_by_author)
        super().save(*args, **kwargs)

这是我的网址:

from django.urls import path
from dashboard.views import BookListView, BookCreateView, BookUpdateView, BookDeleteView

urlpatterns = [
    path("", BookListView.as_view(), name="dashboard-home"),
    path("add_book/", BookCreateView.as_view(), name="dashboard-upload-book"),
    path("edit_book/<slug>/", BookUpdateView.as_view(), name="dashboard-edit-book"),
    path("delete_book/<slug>/", BookDeleteView.as_view(), name="dashboard-delete-book")
]

我的测试失败并出现此错误:

...
AssertionError: 200 != 302 : Response didn't redirect as expected: Response code was 200 (expected 302)
...

请帮忙。

标签: pythondjangounit-testing

解决方案


Daniel Roseman 和 dirkgroten 帮助确定了评论中的问题。

我建议查看 dirkgroten 提到的问题(如何在 django 中对文件上传进行单元测试

self.another_demo_book_kwargs问题在于测试设置中创建的文件字段。

文件字段需要一个实际的文件,而不仅仅是一个路径。

这:

self.another_demo_book_kwargs = {
            "title": "Demo Title",
            "author": "Demo Author",
            "subject": "Another Demo Subject",
            "details": "Another Demo Details",
            "file": "path/to/another/demo/file"
        }

应该替换为:

with open(ABSOLUTE_FILE_PATH) as file_object:
            data = {
                "title": "Demo Title",
                "author": "Demo Author",
                "subject": "Another Demo Subject",
                "details": "Another Demo Details",
                "file": file_object
            }
            response = self.client.post(self.book_create_url, data)

推荐阅读