Search code examples
djangodjango-templatesdjango-tests

Django view unit test conflict with custom template tag


I create a custom templatetag for my django project that returns an image url as favicon

# myapp/templatetags/customtags.py

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

and use it in base.html like this

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

this part works great but after create test function to testing my view got an AttributeError as follow

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

and this is my test 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)

Note: with out template tag it works well


Solution

  • The test database is empty (unless if course you populate it). If there are no Shop objects, then Shop.objects.first() thus 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()
            shop.favicon = 'path/to/some/favicon.ico'
            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)

    That being said, it might be better to add a "fallback" mechanism to your template tag, like:

    # myapp/templatetags/customtags.py
    
    @register.simple_tag
    def get_shop_favicon():
        '''
        get shop favicon
        '''
        shop = Shop.objects.first()
        if shop:
            return shop.favicon.url
        return 'some_default_favicon.ico'