S.j*_*kib 5 python django tdd mocking python-unittest
我在这里有一个视图,它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})
Run Code Online (Sandbox Code Playgroud)
但是当我尝试使用patchfrom模拟模型类和表单类时会出现问题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)
Run Code Online (Sandbox Code Playgroud)
当我运行测试时,我收到如下错误:
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
Run Code Online (Sandbox Code Playgroud)
重定向功能似乎不适用于模拟对象。我怎样才能解决这个问题?我正在使用 Django 2.0.1
我正在学习相同的教程,并且遇到了相同的错误,但是我在这里找到了解决方案:Mock() function gets TypeError in django2
原因是:
Django 2 在某些地方不再支持字节串,因此当视图重定向模拟类列表时,它会作为模拟对象执行,并且 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()))而不是返回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})
Run Code Online (Sandbox Code Playgroud)