Django 视图单元测试与自定义模板标签冲突

Django view unit test conflict with custom template tag

我为我的 django 项目创建了一个自定义模板标签,returns 图像 url 作为收藏夹图标

# myapp/templatetags/customtags.py

@register.simple_tag
def get_shop_favicon():
    '''
    get shop favicon
    '''
    return Shop.objects.first().favicon.url

并像这样在base.html中使用它

<!doctype html>
{% load storefront_tags %}
<head>
    <link rel="icon" href="{% get_shop_favicon %}" type="image/png" sizes="16x16"> 
</head>
<body>
  ...
</body>

这部分效果很好,但是在创建测试函数来测试我的视图后得到了一个 AttributeError,如下所示

AttributeError: 'NoneType' object has no attribute 'favicon'

这是我的测试class

# test.py
from django.test import TestCase
from django.urls import reverse

class ProductViewTest(TestCase):
    '''
    testing product views and urls
    '''
    def test_get_product_list_status_code(self):
        '''
        test to get all products
        '''
        url = reverse('prodcuts') # url name
        response = self.client.get(url)
        self.assertEqual(response.status_code, 200)

注意:没有模板标签效果很好

测试数据库为空(除非您填充它)。如果没有 Shop 个对象,则 Shop.objects.first() 因此 returns None.

# test.py
from django.test import TestCase
from django.urls import reverse

class ProductViewTest(TestCase):
    '''
    testing product views and urls
    '''

    def setUp(self):
        super().setUp()
        shop = Shop()
        <b>shop.favicon = 'path/to/some/favicon.ico'</b>
        shop.save()


    def test_get_product_list_status_code(self):
        '''
        test to get all products
        '''
        url = reverse('prodcuts') # url name
        response = self.client.get(url)
        self.assertEqual(response.status_code, 200)

也就是说,最好在模板标签中添加 "fallback" 机制,例如:

# myapp/templatetags/customtags.py

@register.simple_tag
def get_shop_favicon():
    '''
    get shop favicon
    '''
    shop = Shop.objects.first()
    <b>if shop</b>:
        return shop.favicon.url
    return <b>'some_default_favicon.ico'</b>

您可能会在模板中添加一个检查,以首先查看是否有任何 Shop 对象:

@register.simple_tag
def get_shop_favicon():
    '''
    get shop favicon
    '''
    if Shop.objects.first():
        return Shop.objects.first().favicon.url  
    # else return some placeholder url