如何测试Django的UpdateView?

时间:2018-02-15 19:25:08

标签: python django

作为简化示例,我为UpdateView模型编写了Book,并在成功时为ListView重定向:

from django.urls import reverse
from django.views.generic import ListView
from django.views.generic.edit import UpdateView
from .models import Book


class BookUpdate(UpdateView):
    model = Book
    fields = ['title', 'author']


class BookList(ListView):
    model = Book

Book模型定义为

class Book(models.Model):
    title = models.CharField(max_length=100)
    author = models.CharField(max_length=100, blank=True)

    def get_absolute_url(self):
        return reverse('books-list')

其中urls.py

from django.urls import path
from books.views import BookUpdate, BookList


urlpatterns = [
    path('books/', BookList.as_view(), name='books-list'),
    path('book/<int:pk>/', BookUpdate.as_view(), name='book-update')
]

books/tests.py中,我试图编写以下测试:

class BookUpdateTest(TestCase):
    def test_update_book(self):
        book = Book.objects.create(title='The Catcher in the Rye')

        response = self.client.post(
            reverse('book-update', kwargs={'pk': book.id}), 
            {'author': 'J.D. Salinger'})

        self.assertEqual(response.status_code, 200)

        book.refresh_from_db()
        self.assertEqual(book.author, 'J.D. Salinger')

但是,此测试失败是因为book authorPOST请求后似乎没有更新,即使在从数据库刷新后也是如此:

FAIL: test_update_book (books.tests.BookUpdateTest)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/Users/kurtpeek/Documents/Scratch/book_project/books/tests.py", line 46, in test_update_book
    self.assertEqual(book.author, 'J.D. Salinger')
AssertionError: '' != 'J.D. Salinger'
+ J.D. Salinger

另一方面,如果我运行开发服务器并手动填写字段,一切似乎都按预期工作。如何为UpdateView编写一个单元测试,用于捕获用户更新字段,提交表单以及更改相应的对象?

2 个答案:

答案 0 :(得分:7)

如果您POST表单,您必须发布所有必填字段,而不仅仅是您要更新的字段 - 即使基础模型的必填字段已经有值。此外,成功更新后返回的状态代码为302'Find',而不是200'Oct'。因此,以下测试通过:

class BookUpdateTest(TestCase):
    def test_update_book(self):
        book = Book.objects.create(title='The Catcher in the Rye')

        response = self.client.post(
            reverse('book-update', kwargs={'pk': book.id}), 
            {'title': 'The Catcher in the Rye', 'author': 'J.D. Salinger'})

        self.assertEqual(response.status_code, 302)

        book.refresh_from_db()
        self.assertEqual(book.author, 'J.D. Salinger')

答案 1 :(得分:0)

在 Django 3.2 中,您可以在这里找到规范的解决方案: https://docs.djangoproject.com/fr/3.2/ref/urlresolvers/

在测试中,您只需要:

  • 使用包含在 slug 中的值创建对象,
  • 然后,使用以下参数将其反转:
 self.topic = Book.objects.create(slug="test-update")
        self.response = self.client.get(reverse('book_update', args=[self.topic.slug]))