Opened 6 years ago
Closed 6 years ago
#30089 closed Bug (invalid)
TestClient doesn't accept data with duplicate keys (SELECT multiple)
Reported by: | Adam Gilman | Owned by: | nobody |
---|---|---|---|
Component: | Testing framework | Version: | dev |
Severity: | Normal | Keywords: | |
Cc: | Triage Stage: | Unreviewed | |
Has patch: | no | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description (last modified by )
When constructing tests for forms with SELECT elements which allow multiple item selection, the test client doesn't accept multiple selections due to the fact it uses dict internally and results in a squashed single key
Failing test
def test_post_multi_select(self): "POST SELECT multiple data to a view" post_data = QueryDict(mutable=True) post_data.update({'value':37}) post_data.update({'value':38}) response = self.client.post('/post_view/', post_data) # Check some response details self.assertEqual(response.status_code, 200) self.assertEqual(response.context['data'], ['37', '38']) self.assertEqual(response.templates[0].name, 'POST Template') self.assertContains(response, 'Data received')
*updated
Change History (10)
comment:1 by , 6 years ago
Easy pickings: | unset |
---|
comment:2 by , 6 years ago
Resolution: | → invalid |
---|---|
Status: | new → closed |
comment:3 by , 6 years ago
Apologies, typo in my original test. Good catch. Updated test in description and failure below:
FAIL: test_post_multi_select (test_client.tests.ClientTest) POST SELECT multiple data to a view ---------------------------------------------------------------------- Traceback (most recent call last): File "/Users/dev2/.pyenv/versions/3.7.0/lib/python3.7/unittest/case.py", line 59, in testPartExecutor yield File "/Users/dev2/.pyenv/versions/3.7.0/lib/python3.7/unittest/case.py", line 615, in run testMethod() File "/Users/dev2/Documents/GitHub/django/tests/test_client/tests.py", line 113, in test_post_multi_select self.assertEqual(response.context['data'], ['37', '38']) File "/Users/dev2/.pyenv/versions/3.7.0/lib/python3.7/unittest/case.py", line 839, in assertEqual assertion_func(first, second, msg=msg) File "/Users/dev2/.pyenv/versions/3.7.0/lib/python3.7/unittest/case.py", line 832, in _baseAssertEqual raise self.failureException(msg) AssertionError: '38' != ['37', '38']
comment:4 by , 6 years ago
Resolution: | invalid |
---|---|
Status: | closed → new |
comment:5 by , 6 years ago
Description: | modified (diff) |
---|
comment:6 by , 6 years ago
I'm not sure the test is right here.
post_view
isn't using getlist()
, so even if POST
is a QueryDict
, we'll only get the single value...
c = Context({'data': request.POST['value']})
follow-up: 8 comment:7 by , 6 years ago
Triage Stage: | Unreviewed → Accepted |
---|---|
Type: | Uncategorized → Bug |
Version: | 2.1 → master |
But this fails:
post_data = QueryDict(mutable=True) post_data.update({'value':37}) post_data.update({'value':38}) self.assertEqual(post_data.getlist('value'), [37, 38]) request = RequestFactory().post('/post_view/', post_data) self.assertEqual(request.POST.getlist('value'), ['37', '38'])
self.assertEqual(request.POST.getlist('value'), ['37', '38']) AssertionError: Lists differ: ['38'] != ['37', '38']
So this looks valid.
comment:8 by , 6 years ago
Replying to Carlton Gibson:
request.POST is actual representation of request.body. A post request could have only one parameter of the same name in its body. That's why it returns a single element. I don't think if it's a bug.
comment:9 by , 6 years ago
I didn't look into the cause of the issue but normally a dictionary rather than a QueryDict
is used as test client data.
post_data = {'value': [37, 38]}
passes the test.
comment:10 by , 6 years ago
Resolution: | → invalid |
---|---|
Status: | new → closed |
Triage Stage: | Accepted → Unreviewed |
Then it’s incorrect usage. Good. Thanks both!
It looks like you have a bug in your reported test case, you are updating
post_data
twice with{'value':37}
and never including38
.Please re-open if you reproduce with
.update({'value':38})
.