我在这里有一个视图,它将新的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})
但是当我尝试使用patch
unitest.mock
来模拟模型类和表单类时,会出现问题
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
答案 0 :(得分:0)
我正在经历与您相同的tutorial,并且“ quote_from_bytes()预期的字节数”错误也给我带来了问题。作者使用的是django 1.11,显然重定向和渲染在模拟方面起到了很好的作用。
为此,我的解决方案是在导致问题的时候模拟重定向和渲染功能。例如,这会导致错误,因为它将导致重定向被调用:
def test_passes_POST_data_to_NewListForm(self, mockNewListForm):
response = new_list2(self.request)
mockNewListForm.assert_called_once_with(data=self.request.POST)
但是,当我们模拟重定向时,不会调用Django的重定向,并且不会出现错误:
@patch('lists.views.redirect')
def test_passes_POST_data_to_NewListForm(
self, mock_redirect, mockNewListForm
):
response = new_list2(self.request)
mockNewListForm.assert_called_once_with(data=self.request.POST)
答案 1 :(得分:0)
我正在学习相同的教程,并且遇到相同的错误,但是我在这里找到了解决方法:Mock() function gives TypeError in django2
原因是:
Django 2在某些地方不再支持字节串,因此,当视图重定向模拟类列表时,它作为模拟对象运行,并且iri_to_uri django函数引发错误。
在django 1.11中,iri_to_uri强制将iri转换为字节返回引号(force_bytes(iri),safe =“ /#%[] =:; $&()+,!? @'〜”)代替现在是返回引号(iri,safe =“ /#%[] =:; $&()+,!? @'〜”)。
因此解决方案是返回redirect(str(list_.get_absolute_url())),而不是返回list.views.py中的redirect(list _)
这是我的例子:
playerSharedPref!!.getString("name", "")!!
答案 2 :(得分:0)
请参阅我的 answer here,它仅更改测试代码,同时生成所需的生产代码。