我正在将webapp2与webapp2_extras.i18n一起用于Google App Engine应用。
我有一个单元测试脚本,如下面所述:https://developers.google.com/appengine/docs/python/tools/localunittesting
测试脚本导入模型并且不包含webapp2处理程序,因为测试的目标是业务逻辑代码,而不是请求和响应。但是,我的某些模型会调用format_currency
或gettext
等i18n函数,这会导致错误:
AssertionError: Request global variable is not set.
如何在不实例化webapp2应用程序和请求的情况下初始化i18n模块?
答案 0 :(得分:4)
我遇到了同样的问题(但对于uri_for)我最终在测试中做了以下事情:
app = webapp2.WSGIApplication(
[webapp2.Route('/', None, name='upload_handler')])
request = webapp2.Request({'SERVER_NAME':'test', 'SERVER_PORT':80,
'wsgi.url_scheme':'http'})
request.app = app
app.set_globals(app=app, request=request)
# call function that uses uri_for('upload_handler')
我必须进行反复试验才能猜出必须在请求中设置哪些环境变量。也许你需要添加更多才能拨打i18n。
答案 1 :(得分:0)
尝试模拟你的功能。
示例:我有一个名为users的脚本,可以像这样导入i18n:
from webapp2_extras.i18n import gettext as _
所以在我的测试中我嘲笑这个函数:
from pswdless.model import PswdUserEmail, EmailUserArc
from pswdless.users import FindOrCreateUser
from pswdless import users
# mocking i18n
users._ = lambda s: s
#your tests bellow
您可以将其他功能用于相同的技巧。
我希望它可以帮到你。
答案 2 :(得分:0)
模拟i18n本身似乎很简单。我更喜欢这种方法,因为在单元测试中确实不需要Request和app。
这是一个示例pytest fixture:
@pytest.fixture
def mock_i18n(monkeypatch):
class MockI18n:
def set_locale(self, locale):
pass
def gettext(self, string, **variables):
return string
mock_i18n = MockI18n()
def mock_get_i18n(factory=None, key=None, request=None):
return mock_i18n
from webapp2_extras import i18n
monkeypatch.setattr(i18n, 'get_i18n', mock_get_i18n)
yield
答案 3 :(得分:0)
Mocking似乎确实是这里的方式,但其他答案并不完整和/或比必要的更复杂。这是一个适合我的简单模拟。
=== my_module.py ===
from webapp2_extras.i18n import gettext as _
def f(x):
return _(x)
=== test_my_module.py ===
import my_module
def _mock(x):
return x
@mock.patch("my_module._", side_effect=_mock)
def test_f(self, foo):
y = my_module.f("hello")
self.assertEqual(y, "hello")