【问题标题】:How to get uri_for with webapp2 in unit test?如何在单元测试中使用 webapp2 获取 uri_for?
【发布时间】:2011-11-19 06:06:57
【问题描述】:

我正在尝试使用 webapp2 对处理程序进行单元测试,但遇到了一个愚蠢的小错误。

我希望能够在测试中使用 webapp2.uri_for,但我似乎做不到:

    def test_returns_200_on_home_page(self):
        response = main.app.get_response(webapp2.uri_for('index'))
        self.assertEqual(200, response.status_int)

如果我只是做main.app.get_response('/') 它工作得很好。

收到的异常是:

   Traceback (most recent call last):
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/unittest/case.py", line 318, in run
    testMethod()
  File "tests.py", line 27, in test_returns_200_on_home_page
    webapp2.uri_for('index')
  File "/Users/.../webapp2_example/lib/webapp2.py", line 1671, in uri_for
    return request.app.router.build(request, _name, args, kwargs)
  File "/Users/.../webapp2_example/lib/webapp2_extras/local.py", line 173, in __getattr__
    return getattr(self._get_current_object(), name)
  File "/Users/.../webapp2_example/lib/webapp2_extras/local.py", line 136, in _get_current_object
    raise RuntimeError('no object bound to %s' % self.__name__)
RuntimeError: no object bound to request

我缺少一些愚蠢的设置吗?

【问题讨论】:

    标签: unit-testing google-app-engine webapp2


    【解决方案1】:

    我认为唯一的选择是设置一个虚拟请求,以便能够为测试创建 URI:

    def test_returns_200_on_home_page(self):
        // Set a dummy request just to be able to use uri_for().
        req = webapp2.Request.blank('/')
        req.app = main.app
        main.app.set_globals(app=main.app, request=req)
    
        response = main.app.get_response(webapp2.uri_for('index'))
        self.assertEqual(200, response.status_int)
    

    切勿在测试之外使用set_globals()。由 WSGI 应用程序调用,以线程安全的方式设置活动应用程序和请求。

    【讨论】:

    • 感谢@moraes 的回复。我下班回家后试试看。顺便说一句,我真的很喜欢 webapp2,感谢您与我们分享!
    • 这似乎也不是。现在我收到:文件“/Users/.../webapp2_example/lib/webapp2.py”,第 1671 行,在 uri_for 返回 request.app.router.build(request, _name, args, kwargs) AttributeError: 'NoneType' object没有属性“路由器”
    • 确实,没那么容易。我更正了 sn-p;希望它现在可以工作。
    • 完美,非常感谢您的帮助!!
    【解决方案2】:

    webapp2.uri_for() 假定您处于 Web 请求上下文中,但由于找不到 request 对象而失败。

    您可以将您的应用程序视为一个黑匣子,并使用文字 URI 来调用它,而不是解决这个问题,例如您提到的 '/'。毕竟,你想模拟一个普通的网络请求,而网络浏览器也会使用 URI,而不是内部路由快捷方式。

    【讨论】:

    • 我明白你的意思,但是,将完整的 url 多次放在任何地方都违反了“DRY”原则。如果 url 发生变化,那么在它被字面引用的任何地方都进行更改会更痛苦(并且容易出错),而不是更改 url 路由声明并完成
    • 事实上,webapp-improved.appspot.com/guide/routing.html#extended-routes 指出 DRY 是改进 webapp 的动机之一,“避免在应用程序代码和模板中硬编码 URI”
    猜你喜欢
    • 2012-09-08
    • 2012-06-28
    • 2013-02-04
    • 2011-10-28
    • 2018-02-14
    • 2017-05-06
    • 2012-09-27
    • 2014-01-22
    • 1970-01-01
    相关资源
    最近更新 更多