У меня есть веб-приложение Tornado, которое отправляет запросы внешним службам и, похоже, не может смоделировать ответы на эти запросы.
Я пробовал tornado-http-mock
и mock
libsно безуспешно.
Начальная точка приложения app.py
:
import tornado.ioloop
import tornado.web
from handlers import HealthCheckHandler, MainHandler, LoginHandler, PaymentHandler, UserDetailsHandler
from settings import PORT, tornado_settings
def make_app(settings):
handlers = [
('/static/(.*)', tornado.web.StaticFileHandler, {'path': './public'}),
('/', MainHandler),
('/health', HealthCheckHandler),
('/login', LoginHandler),
('/user', UserDetailsHandler),
('/payment', PaymentHandler),
]
return tornado.web.Application(handlers=handlers, **settings)
if __name__ == '__main__':
app = make_app(tornado_settings)
app.listen(PORT)
tornado.ioloop.IOLoop.current().start()
Я пытаюсь проверить функциональность входа (это сервер OAuth2), который перенаправляет пользователя, когда естьнет code
Передан параметр GET (если пользователь еще не вошел в систему) или он пытается обменять код с токеном доступа.Вот обработчик входа в систему.
import base64
import urllib.parse
import json
import traceback
import tornado.web
import tornado.httpclient
from .base import BaseHandler
from settings import OID_AUTH_API, OID_REDIRECT_URI, OID_CLIENT_ID, OID_CLIENT_PASSWORD
from lib import logger
class LoginHandler(BaseHandler):
_redirect_uri = urllib.parse.quote(OID_REDIRECT_URI, safe='')
_scope = 'openid+profile+email'
_response_type = 'code'
_http_client = tornado.httpclient.AsyncHTTPClient()
async def get(self):
try:
code = self.get_argument('code', None)
if (code is None):
self.redirect('%s/authorization?client_id=%s&scope=%s&response_type=%s&redirect_uri=%s' % (
OID_AUTH_API, OID_CLIENT_ID, self._scope, self._response_type, self._redirect_uri), self.request.uri)
return
# exchange the authorization code with the access token
grant_type = 'authorization_code'
redirect_uri = self._redirect_uri
authorization_header = '%s:%s' % (
OID_CLIENT_ID, OID_CLIENT_PASSWORD)
authorization_header_encoded = base64.b64encode(
authorization_header.encode('UTF-8')).decode('UTF-8')
url = '%s/token?grant_type=%s&code=%s&redirect_uri=%s' % (
OID_AUTH_API, grant_type, code, redirect_uri)
token_exchange_response = await self._http_client.fetch(
url,
method='POST',
headers={
'Content-Type': 'application/x-www-form-urlencoded',
'Authorization': 'Basic %s' % authorization_header_encoded,
'Accept': 'application/json'
},
body='')
token_exchange_response_body_dict = json.loads(
token_exchange_response.body)
access_token = token_exchange_response_body_dict.get('access_token')
self.send_response({
'access_token': access_token
})
except Exception as error:
logger.log_error_with_traceback(error)
self.send_response({
'success': False,
'message': 'Internal server error. Please try again later.'
}, 500)
У меня есть два вопроса: 1. Как проверить функциональность перенаправления в случае, если код авторизации не был представлен?2. Как в этом случае макетировать запросы к серверу OAuth2?
Я пытался с tornado-http-mock
, но я получаю ошибки.
import app
import json
from tornado.httpclient import HTTPClient, HTTPResponse, HTTPRequest, HTTPError
from tornado.testing import AsyncHTTPTestCase, AsyncTestCase, AsyncHTTPClient
from tornado_mock.httpclient import get_response_stub, patch_http_client, set_stub
from .base import TestHandlerBase
from settings import OID_AUTH_API
class TestLoginHandler(AsyncHTTPTestCase):
def get_app(self):
test_app = app.make_app({})
self.app_http_client = test_app.http_client = AsyncHTTPClient(force_instance=True)
return test_app
def test_token_code_exchange(self):
patch_http_client(self.app_http_client)
set_stub(self.app_http_client, '%s/token' % (OID_AUTH_API), request_method='POST', response_body='oauth_server_token')
response = self.fetch('/login?code=123')
self.assertEqual(response.code, 200)
print(response.body)
Я получаю следующую ошибкучто указывает на то, что метод POST не поддерживается (кажется, что запрос на самом деле отправляется на сервер и не подвергается мошенничеству).
Login Error code: 405 | Response body:
[E 190626 13:29:33 web:2246] 500 GET /login?code=123 (127.0.0.1) 238.10ms
======================================================================
FAIL: test_token_code_exchange (tests.handlers.login.TestLoginHandler)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/Users/.../venv/lib/python3.7/site-packages/tornado/testing.py", line 98, in __call__
result = self.orig_method(*args, **kwargs)
File "/Users/.../tests/handlers/login.py", line 60, in test_token_code_exchange
self.assertEqual(response.code, 200)
AssertionError: 500 != 200
Я ожидаю получить ответ с заглушкой, но, очевидно,Я не понимаю этого.Что мне здесь не хватает?Есть ли другое решение для этого?