简体   繁体   English

如何在Django管理员页面的单元测试中对用户进行身份验证?

[英]How to authenticate a user in a unit test for the Django admin page?

I'm trying to adapt the answer from Testing custom admin actions in django , but I'm running into some unexpected behavior. 我正在尝试改编django中的“测试自定义管理员操作”中的答案,但是我遇到了一些意外行为。 I've created a simplified Django app, myapp , which has a Worker and Invoice model: 我创建了一个简化的Django应用程序myapp ,它具有一个WorkerInvoice模型:

class Worker(models.Model):
    name = models.CharField(max_length=255)


class Invoice(models.Model):
    UNPAID = 0
    PAID = 1

    worker = models.ForeignKey(
        'Worker', on_delete=models.CASCADE)
    amount = models.DecimalField(
        max_digits=10, decimal_places=2)
    amount_paid = models.DecimalField(
        max_digits=10, decimal_places=2, default=Decimal('0.00'))
    status = models.IntegerField(
        choices=[(UNPAID, 'Unpaid'), (PAID, 'Paid')], default=0)

I've create a custom admin action called mark_as_paid which changes the status of the selected invoices to Invoice.PAID in admin.py : 我创建了一个名为mark_as_paid的自定义管理操作, Invoice.PAID中选定发票的状态更改为admin.py

from django.contrib import admin
from django.db.models import F

from .models import Invoice


@admin.register(Invoice)
class InvoiceAdmin(admin.ModelAdmin):
    list_display = ('worker', 'status', 'amount', 'amount_paid')
    actions = ['mark_as_paid']

    def mark_as_paid(self, request, queryset):
        queryset.update(amount_paid=F('amount'))

I'm trying to test this like so: 我正在尝试像这样测试:

from decimal import Decimal

from django.contrib import admin
from django.contrib.auth.models import User
from django.test import TestCase
from django.urls import reverse

from myapp.models import Invoice, Worker


class InvoiceAdminTests(TestCase):
    def setUp(self):
        self.user = User.objects.create_user(
            username='foobar',
            email='foo@bar.com',
            password='barbaz',
            is_superuser=True)
        self.client.force_login(user=self.user)

    def test_mark_as_paid(self):
        worker = Worker.objects.create(name="John Doe")
        invoice = Invoice.objects.create(
            worker=worker, amount=Decimal('100.00'))

        response = self.client.post(
            reverse('admin:myapp_invoice_changelist'),
            data={
                'action': 'mark_as_paid',
                admin.ACTION_CHECKBOX_NAME: [invoice.id]})

        import ipdb; ipdb.set_trace()

        invoice.refresh_from_db()
        self.assertEqual(invoice.amount_paid, Decimal('100.00'))

I've set a debugger trace in the test, but ultimately I would expect it to pass. 我已经在测试中设置了调试器跟踪,但是最终我希望它能够通过。 Currently, however, it is failing because invoice.amount_paid is still Decimal('0.00') . 但是,由于invoice.amount_paid仍为Decimal('0.00') ,因此当前失败。

Strangely, the response has a status code of 302 (not 200) and empty content: 奇怪的是,响应的状态码为302(不是200),内容为空:

ipdb> response.status_code                                                               
302
ipdb> response.content                                                                   
b''

I've also set a trace in the mark_as_paid() method and it's not getting hit, so I suspect there is something wrong about the way I'm mocking the authentication of the user, since if I create a superuser with python manage.py createsuperuser and test this manually, everything works as expected. 我还在mark_as_paid()方法中设置了一个跟踪,但是没有被击中,所以我怀疑mark_as_paid()用户身份验证的方式存在问题,因为如果我使用python manage.py createsuperuser创建一个超级用户, python manage.py createsuperuser并手动进行测试,一切正常。

Any idea what is wrong with this approach? 知道这种方法有什么问题吗?

Looking at the example at Testing custom admin actions in django more closely, it turns out I need to use the create_superuser() method instead of create_user() with is_superuser=True . 纵观一下例子在Django测试自定义管理行为更加紧密,事实证明,我需要使用create_superuser()方法,而不是create_user()is_superuser=True The test passes with the following modified setUp() method: 测试通过以下修改的setUp()方法:

class InvoiceAdminTests(TestCase):
    def setUp(self):
        self.user = User.objects.create_superuser(
            username='foobar',
            email='foo@bar.com',
            password='barbaz')
        self.client.force_login(user=self.user)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM