Houman
Houman

Reputation: 66380

How to pass/mock the admin_required decorator in gae?

class Generator(Resource):

    @admin_required
    def get(self):
       pass

If I add the @admin_required decorator on my view, the unit test start failing, with the message:

RuntimeError: working outside of request context

Is there a way to mock it or bypass it for unit tests?

Here is the decorator:

def admin_required(func):
    """Requires App Engine admin credentials"""
    @wraps(func)
    def decorated_view(*args, **kwargs):
        if users.get_current_user():
            if not users.is_current_user_admin():
                abort(401)  # Unauthorized
            return func(*args, **kwargs)
        return redirect(users.create_login_url(request.url))
    return decorated_view

Upvotes: 1

Views: 576

Answers (1)

mgilson
mgilson

Reputation: 310187

I'd just patch the users module:

from google.appengine.api import users

# ...

@mock.patch.object(users, 'get_current_user')
@mock.patch.object(users, 'is_current_user_admin', return_value=True)
def test_handler(mock_get_current_user, mock_is_current_user_admin):
    invoke_your_handler()
    # make assertions, etc.

If you want to go deeper, you could use that GAE testbed ... Unfortunately, the documentation here seems to be pretty poor and tricky to get right... Based on this answer, it looks like you need to create a testbed instance and then set the environment:

from google.appengine.ext import testbed

testbed = testbed.TestBed()
testbed.activate()
testbed.init_user_stub()
# Sets environment variables...
testbed.setup_env(
    user_email='[email protected]',
    user_id='123456',
    user_is_admin='1',  # '1' is an admin, '0' is a non-admin.
    overwrite=True,
)

Now continue your test as usual. If you are using unittest for testing, you'd probably want to pack all of that fun stuff into your setUp method.

Also note, in order to avoid polluting your environment, you'll want to call testbed.deactivate() at the end of the test.

Upvotes: 3

Related Questions