- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我有一个 Tornado Web 应用程序,它向外部服务发送请求,但似乎无法模拟这些请求的响应。
我尝试过 tornado-http-mock
和 mock
库,但没有成功。
应用程序起始点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 参数(如果用户尚未登录)时,该功能会重定向用户,或者它尝试用访问 token 交换代码。这是登录处理程序。
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
我期待得到 stub 回复,但显然,我没有得到。我在这里缺少什么?还有其他解决办法吗?
最佳答案
您可以使用mock.patch和gen.coroutine来模拟tornado中的外部请求。你可以尝试这样的事情:
将外部请求提取到类似...的方法
async def new_fetch(self, url, authorization_header_encoded):
return 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='')
更改您的 LoginHandler 以调用此新方法:
token_exchange_response =等待new_fetch(url,authorization_header_encoded)
在您的 TestLoginHandler 中创建一个新方法来模拟 http 响应,并使用 gen.coroutine 装饰器装饰此方法,并使用 mock.patch 装饰器在您的测试方法上模拟外部请求方法:
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,
from tornado import gen
from .base import TestHandlerBase
from settings import OID_AUTH_API
class TestLoginHandler(AsyncHTTPTestCase):
@gen.coroutine
def mock_fetch(self, url, authorization_header_encoded)
request = HTTPRequest(
headers=authorization_header_encoded,
method='POST',
body='',
url=url)
resp = HTTPResponse(request, HTTPStatus.OK, buffer=json.dumps({}))
resp._body = json.dumps({"YOUR_RESPONSE_BODY":"YOUR_RESPONSE_BODY"})
return resp
def get_app(self):
test_app = app.make_app({})
# self.app_http_client = test_app.http_client = AsyncHTTPClient(force_instance=True)
return test_app
@mock.patch("full.path.to.LoginHandler.new_fetch")
def test_token_code_exchange(self, mocked_method):
mocked_method.return_value = self.mock_fetch('optional_url', 'optional_header')
# 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)
我没有测试这段代码,我编写只是为了向您传递制作此模拟的想法,所以也许您需要调整这段代码中的一些内容
关于python - 模拟 Tornado AsyncHTTPClient 请求/响应,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56770795/
根据一些谷歌搜索,我安装了以下错误处理程序。然而,似乎返回 http 500 的 python 异常并没有被这些东西捕获,尽管 404 是这样。通过我在下面的代码中留下的打印语句,我可以看到它没有命中
我刚刚意识到 WebSocketHandler.write_message() 返回一个 Future。我以前没有在我的函数中产生过这个函数: @tornado.gen.coroutine
这是我的 Tornado 文件:: from tornado.wsgi import WSGIContainer from tornado.ioloop import IOLoop from torn
class MainHandler(BaseHandler): @tornado.web.authenticated def get(self): self.rende
我正在尝试使用 AsyncHTTPTestCase 测试 Tornado .我想测试标有 @tornado.web.authenticated 注释的处理程序。因为此处理程序需要身份验证,所以我们必须
我正在使用 Tornado Web Server (版本 4.1)使用 Python 2.7 创建 REST Web 应用程序。我的请求处理程序之一 (web.RequestHandler) 使用多部
我想知道tornado 的内部工作流程,并且看过this article ,很好,但我就是想不通 ioloop.py里面有这样一个函数 def add_handler(self, fd, handle
如何遍历从 Python/Tornado 处理程序传递到 Tornado 模板的字典? 我试过 {% for key, value in statistics %}
我有一个 Tornado 后端,为 Angular 前端提供服务。更新数据库时,tornado api 不会获取更新的数据。它仅在我重新启动服务器后出现。有人可以帮我解决这个问题吗?我希望获取的数据能
我尝试使用自定义的 WSGIContainer 来处理异步操作: from tornado import httpserver, httpclient, ioloop, wsgi, gen @gen.
from tornado.web import RequestHandler class HelloWorldHandler(RequestHandler): def get(self):
Pylint 遇到 @tornado.web.authenticated 时崩溃 class Handler1(tornado.web.RequestHandler): def get(sel
经过 tornado.gen documentation有人可以帮我理解 tornado.gen.coroutine 和 tornado.gen.engine 之间的确切区别 最佳答案 正如 gen.
代码如下: from tornadoredis import Client from tornado.ioloop import IOLoop from tornado.gen import coro
我有一个 tornado.websocket.WebSocketHandler 的子类。在该类中,我有一个方法使用 Django ORM 从子类模型中获取用户:django.contrib.auth.
我是 ssl 之类的新手,我已经使用 openssl 生成了自签名证书。 openssl req -newkey rsa:2048 -nodes -keyout key.pem -x509 -days
我已经从 tornado 4.2 移动到 tornado 6.0.3,我得到了错误 AttributeError:模块“tornado.web”没有属性“异步” 根据 tornado v6 seems
我一直在关注此 ( https://developer.ibm.com/tutorials/se-distributed-apps-zeromq-part2/) 教程,以设置使用 CurveZMQ 加
我在使用tornado-celery整合tornado和celery时,出现错误:``` traceback (most recent call last): File "/usr/local/l
我正在使用 Tornado 与 twitter 等第三方进行身份验证。 我的登录处理程序看起来像这样 class AuthLoginHandler(BaseHandler, tornado.auth.
我是一名优秀的程序员,十分优秀!