python - 模拟 Django 模型类时无法重定向

标签 python django mocking tdd python-unittest

我这里有一个 View ,它向数据库添加一个新的 List 并重定向到 List 页面。我在模型类中配置了 get_absolute_url。它似乎工作得很好。

def new_list(request):
    form = ItemForm(request.POST)

    if form.is_valid():
        list_ = List()
        list_.owner = request.user
        list_.save()
        form.save(for_list=list_)
        return redirect(list_)
    else:
        return render(request, 'home.html', {'form': form})

但是当我尝试使用 unitest.mock 中的 patch 模拟模型类和表单类时,问题发生了

class TestMyLists(TestCase):

    @patch('lists.views.List')
    @patch('lists.views.ItemForm')
    def test_list_owner_is_saved_if_user_is_authenticated(
        self, mockItemFormClass, mockListClass
    ):
        user = User.objects.create(email='a@b.com')
        self.client.force_login(user)
        self.client.post('/lists/new', data={'text': 'new item'})
        mock_list = mockListClass.return_value
        self.assertEqual(mock_list.owner, user)

当我运行测试时,出现如下错误:

Traceback (most recent call last):
File "/home/sjsakib/.virtualenvs/superlists/lib/python3.6/site-packages/django/core/handlers/exception.py", line 35, in inner
  response = get_response(request)
File "/home/sjsakib/.virtualenvs/superlists/lib/python3.6/site-packages/django/core/handlers/base.py", line 128, in _get_response
  response = self.process_exception_by_middleware(e, request)
File "/home/sjsakib/.virtualenvs/superlists/lib/python3.6/site-packages/django/core/handlers/base.py", line 126, in _get_response
  response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/mnt/BAC4BB93C4BB4FFD/codes/tdd/superlists/lists/views.py", line 36, in new_list
  return redirect(list_)
File "/home/sjsakib/.virtualenvs/superlists/lib/python3.6/site-packages/django/shortcuts.py", line 58, in redirect
  return redirect_class(resolve_url(to, *args, **kwargs))
File "/home/sjsakib/.virtualenvs/superlists/lib/python3.6/site-packages/django/http/response.py", line 407, in __init__
  self['Location'] = iri_to_uri(redirect_to)
File "/home/sjsakib/.virtualenvs/superlists/lib/python3.6/site-packages/django/utils/encoding.py", line 151, in iri_to_uri
  return quote(iri, safe="/#%[]=:;$&()+,!?*@'~")
File "/usr/local/lib/python3.6/urllib/parse.py", line 787, in quote
  return quote_from_bytes(string, safe)
File "/usr/local/lib/python3.6/urllib/parse.py", line 812, in quote_from_bytes
  raise TypeError("quote_from_bytes() expected bytes")
TypeError: quote_from_bytes() expected bytes

重定向功能似乎不适用于模拟对象。我怎样才能解决这个问题? 我正在使用 Django 2.0.1

最佳答案

我正在学习相同的教程,但我遇到了相同的错误,但我在这里找到了解决方案:Mock() function gives TypeError in django2

原因是:

Django 2 在某些地方不再支持字节串,因此当 View 重定向模拟类列表时,它作为模拟对象执行并且 iri_to_uri django 函数抛出错误。

在 django 1.11 中,iri_to_uri 强制 iri 返回一个字节 return quote(force_bytes(iri), safe="/#%[]=:;$&()+,!?@'~") 而不是现在是 return quote(iri, safe="/#%[]=:;$&()+,!?@'~")。

所以解决方案是在 lists.views.py 中返回 redirect(str(list_.get_absolute_url())) 而不是 return redirect(list_)

这是我的例子:

def new_list(request):
    form = ItemForm(data=request.POST)
    if form.is_valid():
        list_ = List()
        list_.owner = request.user
        list_.save()
        form.save(for_list=list_)
        return redirect(str(list_.get_absolute_url()))
    else:
        return render(request, 'home.html', {"form": form})

关于python - 模拟 Django 模型类时无法重定向,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48720028/

相关文章:

django - 使用 Django 在 Docker 上设置 RabbitMQ

python - django-cors-headers 不适用于 DRF(Django Rest Framework)

unit-testing - lambda 函数 : TypeError: stripe_1. 默认值不是构造函数上的模拟 Stripe 失败

python - 在单元测试中模拟 FTP

python - 测试 Python AWS Lambda boto3 初始化

python - 将生成的 TFIDF 计算添加到 Pyspark 中原始文档的数据框中

python - Selenium 错误 : Element not found in the cache - perhaps the page has changed since it was looked up

python - Firefox 附加组件 SDK 错误

python - 如何在 django 中使用模型实例给出文件夹名称

python - 当我在 Django 中已有数据迁移时,如何在模型中添加新字段?