0

I'm trying to test that my authentication fails. The exception is raised but not caught by assertRaises. What am I missing here?

def test_auth(self):
    from graphql_jwt.exceptions import PermissionDenied

    with self.assertRaises(PermissionDenied):
        response = self.client.execute(self.query)

Traceback:

Creating test database for alias 'default'...
System check identified no issues (0 silenced).
Traceback (most recent call last):
  File "/home/dan/game/venv/lib/python3.7/site-packages/promise/promise.py", line 487, in _resolve_from_executor
    executor(resolve, reject)
  File "/home/dan/game/venv/lib/python3.7/site-packages/promise/promise.py", line 754, in executor
    return resolve(f(*args, **kwargs))
  File "/home/dan/game/venv/lib/python3.7/site-packages/graphql/execution/middleware.py", line 75, in make_it_promise
    return next(*args, **kwargs)
  File "/home/dan/game/venv/lib/python3.7/site-packages/graphene_django/filter/fields.py", line 106, in connection_resolver
    **args
  File "/home/dan/game/venv/lib/python3.7/site-packages/graphene_django/fields.py", line 156, in connection_resolver
    iterable = resolver(root, info, **args)
  File "/home/dan/game/venv/lib/python3.7/site-packages/graphql_jwt/decorators.py", line 31, in wrapper
    return func(info.context, *args, **kwargs)
  File "/home/dan/game/venv/lib/python3.7/site-packages/graphql_jwt/decorators.py", line 43, in wrapper
    raise exceptions.PermissionDenied()
graphql.error.located_error.GraphQLLocatedError: You do not have permission to perform this action

F.
======================================================================
FAIL: test_auth (api.tests.test_mutations.TestGame)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/dan/game/api/tests/test_mutations.py", line 57, in test_auth
    response = self.client.execute(self.query)
AssertionError: PermissionDenied not raised

The exception is being raised here.

Randy
  • 14,349
  • 2
  • 36
  • 42
dan-klasson
  • 13,734
  • 14
  • 63
  • 101
  • Not reflecting the permission denied error - is this the *same* permission denied exception? Looks like the GraphQLLocatedError being thrown might not be the same one, or there is something in between that catches the permission error and rethrows, but preserves the original trace (a nasty anti pattern) – F1Rumors Jun 20 '19 at 16:00

2 Answers2

2

Your test is not catching a PermissionDenied exception because something in the code you're running is wrapping that exception in an instance of graphql.error.located_error.GraphQLLocatedError. Because you're checking for the wrong exception type, the test fails.

I don't know too much about the libraries you're using, and the invisible change of the exception type seems like a horrible mis-feature (it should at least add the code that changes the exception type to the exception traceback so you can debug it). But you may be able to work around the issue, by catching the wrapped exception and rethrowing the original:

def test_auth(self):
    from graphql_jwt.exceptions import PermissionDenied
    from graphql.error.located_error import GraphQLLocatedError

    with self.assertRaises(PermissionDenied):
        try:
            response = self.client.execute(self.query)
        except GraphQLLocatedError as e:
            raise e.original_error
Blckknght
  • 100,903
  • 11
  • 120
  • 169
  • Actually this does not work and the solution is not that simple unfortunately. Accepted the answer as it's otherwise correct. Would be good for the person who downvoted to explain why. – dan-klasson Jul 03 '19 at 03:12
  • I have a similar problem right now and this solution doesn't work. It still is saying `AssertionError: GraphQLError not raised` – moctarjallo Oct 11 '19 at 03:04
2

GraphQL, by definition catches all exceptions and puts errors in the errors part of the response. If you're testing the execution of a query (self.client.execute(... query ...)) you should get the result and and verify it has an errors part that matches what you expect.

An easier way would be to test the resolver specifically - call resolve_entity directly and not via the GraphQL execution layer, and test it like you would any other Python function.

flamengo
  • 33
  • 5