You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django单元测试重定向报错:dict对象无url属性问题排查

Django视图测试中AttributeError问题解决

问题场景

视图函数代码:

def my_function(request):
    session = create_something('some_random_string')
    return redirect(session.url, code=303)

测试代码:

import unittest
from django.test import TestCase
from unittest.mock import patch
from my_app.views import my_function

class TestMyFunction(TestCase):

    @patch('my_app.views.create_something', return_value={
        "url": "https://tiagoperes.eu/"
    })
    def test_my_function(self, mock_create_something):
        response = self.client.get("/my-function/")

执行测试时报错:

AttributeError: 'dict' object has no attribute 'url'

问题原因

视图里调用create_something后,是通过属性访问(session.url)获取地址的,但测试中mock的返回值是字典,字典只能通过键取值(session["url"]),两者访问方式不匹配,因此触发属性不存在的错误。

解决方法

把mock的返回值改成具有url属性的模拟对象,有两种常用方式:

方法1:使用MagicMock

直接用unittest.mock.MagicMock构造带属性的对象:

from unittest.mock import patch, MagicMock

# ...

@patch('my_app.views.create_something', return_value=MagicMock(url="https://tiagoperes.eu/"))
def test_my_function(self, mock_create_something):
    response = self.client.get("/my-function/")
    # 可添加断言验证结果
    self.assertEqual(response.status_code, 303)
    self.assertEqual(response.url, "https://tiagoperes.eu/")

方法2:构造简单类/namedtuple

如果需要更明确的结构,可以自己定义类或者用collections.namedtuple:

from collections import namedtuple

# ...

SessionMock = namedtuple('SessionMock', ['url'])

@patch('my_app.views.create_something', return_value=SessionMock(url="https://tiagoperes.eu/"))
def test_my_function(self, mock_create_something):
    response = self.client.get("/my-function/")
    # 断言逻辑同上

类似问题场景

  • 当mock Django模型类时,若错误返回字典而非模拟对象,后续代码若期望模型属性,可能触发TypeError: quote_from_bytes() expected bytes错误
  • 未给mock设置return_value时,默认返回的Mock对象若被当作字符串/字节使用,会触发TypeError: expected string or bytes-like object错误

内容的提问来源于stack exchange,提问作者Tiago Peres

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 13:56:05