Flask-socketio: `current_user` from Flask-Login is not captured when using `SocketIO.test_client()`.

Created on 18 Feb 2016  路  9Comments  路  Source: miguelgrinberg/Flask-SocketIO

I can confirm that, like the discussion in #78, I have access to current_user during socket event processing. However, due to the test_client() mechanism bypassing the /socket.io route paths and instead sending Packet objects to the server directly, the copying of the user session state including access to current_user does not occur during test.

I didn't yet dig deeply into the server code that negotiates the websocket to understand how difficult it might be to replicate during test. I think an interface that accepts a Flask.test_client() object and establishes a session state on the server replicating what happens for an actual websocket connection would be preferable.

In the meantime, I think that my only workaround is to spawn a test server using subprocess and send requests, since that should set current_user properly for socket events.

Also related: #197

bug

All 9 comments

The easiest way to have a functioning current_user during tests is to mock it.

How were you planning to get Flask-Login to work in a test. Are you also using the Flask test client to get the authentication processed?

I'll think about this, maybe I can figure out a way to make the Flask test client and the SocketIO test client to work together so that Flask-Login can be used without mocking.

You're correct that mocking works. I didn't think of it initially due to there being a test_client() interface. However, mocking can be brittle and complex if there are several modules working together to implement handler logic. I'm not sure if flask.testing.FlaskClient#session_transaction would be a helpful way to implement something like this. It pushes an application context with the test client's session info.

Edit: Yes, I'm using the Flask test client.

Any update on this?

@srossross it is, in my view, a low priority fix, since mocking current_user works well. I really haven't spent enough time thinking about a clean way to solve this.

馃憤 thanks @miguelgrinberg

I'm struggling with this too. How would you mock current_user?

@ruipacheco you can mock pretty much anything with the mock package. It's part of the standard library in Python 3. For Python 2 you can install it with pip install mock.

I got the method to mock current_user below from here:

import mock  # python2, after pip install mock
from unittest import mock  # python3 

@mock.patch('flask_login.utils._get_user')
def test_something(self, current_user):
    user = User.query.get(1)                      
    current_user.return_value = user
    ...

Implemented in v3.3.0. To make this work, you have to pass the flask_test_client argument when you create the Socket.IO test client. When the Flask test client is given, the Socket.IO test client imports all its cookies. This includes the Flask user session, which is where Flask-Login writes the data that feeds the current_user variable.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

novice79 picture novice79  路  3Comments

hrmon picture hrmon  路  5Comments

ypperlig picture ypperlig  路  5Comments

dlernz picture dlernz  路  4Comments

chaitanyavolkaji picture chaitanyavolkaji  路  3Comments