Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to Replicate Multidict for Flask Post Unit Test Python

So in my flask app, I have a form on the frontend that gets populated with several users. Each user is associated with a checkbox with the name 'selected_user'. On submit, the form is posted through standard HTML form controls (no javascript or manual ajax of any kind).

In the backend, I can parse this using

flask.request.form.getlist('selected_user')

and it returns a list of users as I expect (a user here is itself a dictionary of unique keys and associated values).

Printing out flask.request.form looks like so for example:

ImmutableMultiDict([
  ('_xsrf_token', u'an_xsrf_token_would_go_here'),
  ('selected_user', u'{u\'primaryEmail\': u\'some_value\'}'...),
  ('selected_user', u'{u\'primaryEmail\': u\'some_value\'}'...)])

My problem is, I cannot seem to replicate this format in my unit tests for the life of me. Obviously, I could use some javascript to bundle the checked users on the frontend into an array or whatever and then duplicate that area much easier on the backend, and that may very well be what I end up doing, but that seems like an unnecessary hassle just to make this function testable when it already behaves perfectly in my application.

Here is what I currently have tried in my test, which seems like it should be the correct answer, but it does not work:

mock_users = []
for x in range(0, len(FAKE_EMAILS_AND_NAMES)):
  mock_user = {}
  mock_user['primaryEmail'] = FAKE_EMAILS_AND_NAMES[x]['email']
  mock_user['name'] = {}
  mock_user['name']['fullName'] = FAKE_EMAILS_AND_NAMES[x]['name']
  mock_users.append(mock_user)

data = {}
data['selected_user'] = mock_users

response = self.client.post(flask.url_for('add_user'), data=data,
                            follow_redirects=False)

This gives me an error as follows:

add_file() got an unexpected keyword argument 'primaryEmail'

I've also attempted sending these as query strings, sending data as json.dumps(data), encoding each mock_user as a tuple like this:

data = []
for x in range(0, 3):
  my_tuple = ('selected_user', mock_users[x])
  data.append(my_tuple)

None of these approaches have worked for various other errors. What am I missing here? Thanks ahead of time for any help! Also, sorry if there are an obvious syntax errors as I rewrote some of this for SO instead of copy pasting.

like image 549
eholder0 Avatar asked Jan 15 '16 16:01

eholder0


People also ask

How do you write a unit test case in python flask?

First create a file named test_app.py and make sure there isn't an __init__.py in your directory. Open your terminal and cd to your directory then run python3 app.py . If you are using windows then run python app.py instead. Hope this will help you solve your problem.


1 Answers

You can create a MultiDict, then make it Immutable:

from werkzeug.datastructures import MultiDict, ImmutableMultiDict

FAKE_EMAILS_AND_NAMES = [
    {'email': '[email protected]',
     'name': 'a'},
    {'email': '[email protected]',
     'name': 'b'},
]

data = MultiDict()
for x in range(0, len(FAKE_EMAILS_AND_NAMES)):
  mock_user = {}
  mock_user['primaryEmail'] = FAKE_EMAILS_AND_NAMES[x]['email']
  mock_user['name'] = {}
  mock_user['name']['fullName'] = FAKE_EMAILS_AND_NAMES[x]['name']
  data.add('select_user', mock_user)

data = ImmutableMultiDict(data)

print data

This prints:

ImmutableMultiDict([
    ('select_user', {'primaryEmail': '[email protected]', 'name': {'fullName': 'a'}}),
    ('select_user', {'primaryEmail': '[email protected]', 'name': {'fullName': 'b'}})
])

EDIT:

The line data.add... should probably be data.add('selected_user', json.dumps(mock_user)) since it looks like the output you posted is a JSON encoded string.

like image 95
Charles L. Avatar answered Nov 14 '22 23:11

Charles L.