Python 使用mock模拟导入的模块以测试挂架控制器功能

Python 使用mock模拟导入的模块以测试挂架控制器功能,python,mocking,pyramid,pylons,python-mock,Python,Mocking,Pyramid,Pylons,Python Mock,我一直在关注一个问题,就是如何实现mock来测试一个挂架控制器功能 我尝试测试的特定功能可以在这里找到: 目标: 我只是想模拟它调用的函数,这样我就可以确认它最终调用了get_完备性 问题: 我可以模拟(好),(稳定)(延迟),(失败),(分支)(缓存)很好。但是当涉及到g.buildapi_cache.get_builds_for_revision时,我似乎无法正确地模拟它,每次调用revision(),它都失败了 g实际上是pylons.app_globals,并导入到selfservice

我一直在关注一个问题,就是如何实现mock来测试一个挂架控制器功能

我尝试测试的特定功能可以在这里找到:

目标:

我只是想模拟它调用的函数,这样我就可以确认它最终调用了get_完备性

问题:

我可以模拟(好),(稳定)(延迟),(失败),(分支)(缓存)很好。但是当涉及到g.buildapi_cache.get_builds_for_revision时,我似乎无法正确地模拟它,每次调用revision(),它都失败了

g实际上是pylons.app_globals,并导入到selfservice.py控制器中,如下所示:“从pylons导入app_globals作为g”

测试:

我正在使用python解释器来测试所有这些。以下是我正在尝试的两种实现:和

总而言之,这里是解释器中的完整运行,包括对

>>来自buildapi.controllers.selfservice导入SelfserveController
>>>从mock导入补丁,mock
>>>s=SelfserveController()
>>>s._ok=Mock(name=''u ok')
>>>s.(获取)稳定(延迟=模拟)(返回)值=180)
>>>s._分支_缓存=Mock()
>>>s._分支_缓存={'try':无}
>>>s._failed=Mock(返回_value=“failed”)
>>>使用补丁('buildapi.controllers.selfservice.g.buildapi\u cache.get\u builds\u for\u revision')作为get\u builds\u for\u revision:
...         获取修订版的版本。返回值=['baz','bang']
...         结果=修订('try','bar')
... 
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
文件“/Users/jzeller/buildapi test/lib/python2.7/site packages/mock.py”,第1252行,输入__
self.target=self.getter()
文件“/Users/jzeller/buildapi test/lib/python2.7/site packages/mock.py”,第1414行,在
getter=lambda:\导入器(目标)
文件“/Users/jzeller/buildapi test/lib/python2.7/site packages/mock.py”,第1102行,在
thing=\u dot\u查找(thing、comp、import\u路径)
文件“/Users/jzeller/buildapi test/lib/python2.7/site packages/mock.py”,第1089行,在dot\u查找中
return getattr(事物、公司)
文件“/Users/jzeller/buildapi test/lib/python2.7/site packages/paste/registry.py”,第137行,在__
返回getattr(self.\u current\u obj(),attr)
文件“/Users/jzeller/buildapi test/lib/python2.7/site packages/paste/registry.py”,第197行,位于当前对象中
'线程''%self.\\\\\\\\\\\\\\\\\\\\\\'
TypeError:没有为此线程注册对象(名称:app_globals)
这是给你的

>>来自buildapi.controllers.selfservice导入SelfserveController
>>>从mock导入补丁,mock
>>>s=SelfserveController()
>>>s._ok=Mock(name=''u ok')
>>>s.(获取)稳定(延迟=模拟)(返回)值=180)
>>>s._分支_缓存=Mock()
>>>s._分支_缓存={'try':无}
>>>s._failed=Mock(返回_value=“failed”)
>>>g=Mock()
>>>g.buildapi\u cache=Mock(name='buildapi\u cache')
>>>g.buildapi_cache.get_builds_for_revision=Mock(name='get_builds_for_revision',返回_值=['baz','bang'])
>>>美国修订版('try','bar')
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
文件“buildapi/controllers/selfservice.py”,第217行,修订版
作业\u项=g.buildapi\u缓存。获取\u版本的\u版本(分支,版本)
文件“/Users/jzeller/buildapi test/lib/python2.7/site packages/paste/registry.py”,第137行,在__
返回getattr(self.\u current\u obj(),attr)
文件“/Users/jzeller/buildapi test/lib/python2.7/site packages/paste/registry.py”,第197行,位于当前对象中
'线程''%self.\\\\\\\\\\\\\\\\\\\\\\'
TypeError:没有为此线程注册对象(名称:app_globals)
这与我尝试运行修订版时遇到的错误相同。每次它都会出错,因为我试图模拟这个app_globals模块失败了,或者看起来是这样。我真的不知道还有什么别的办法可以试试有人有什么想法吗?

以下是一些更好的细节:

  • 下面是我尝试使用的函数,它位于我正在实例化的类中:
注1

我已经看过了以下线程,它们似乎不太适用于这个特定场景,或者我完全没有抓住要点


    • 如果没有初始化的挂架环境,控制器不能用作独立对象

      使用Pylons提供的用于测试的功能,可以从测试控制器的所有样板代码中节省您的时间

      我建议您将TestController类与nosetests结合使用,如中所示

      特别是对于您的代码,我认为Pylons对待私有方法(以u开头)的方式与对待公共方法的方式不同,因为公共方法是在请求的上下文中运行的

      >>> from buildapi.controllers.selfserve import SelfserveController
      >>> from mock import patch, Mock
      >>> s = SelfserveController()
      >>> s._ok = Mock(name='_ok')
      >>> s._get_stable_delay = Mock(return_value=180)
      >>> s._branches_cache = Mock()
      >>> s._branches_cache = {'try': None}
      >>> s._failed = Mock(return_value="Failed")
      >>> with patch('buildapi.controllers.selfserve.g.buildapi_cache.get_builds_for_revision') as get_builds_for_revision:
      ...         get_builds_for_revision.return_value = ['baz', 'bang']
      ...         result = revision('try', 'bar')
      ... 
      Traceback (most recent call last):
        File "<stdin>", line 1, in <module>
        File "/Users/jzeller/buildapi-test/lib/python2.7/site-packages/mock.py", line 1252, in __enter__
          self.target = self.getter()
        File "/Users/jzeller/buildapi-test/lib/python2.7/site-packages/mock.py", line 1414, in <lambda>
          getter = lambda: _importer(target)
        File "/Users/jzeller/buildapi-test/lib/python2.7/site-packages/mock.py", line 1102, in _importer
          thing = _dot_lookup(thing, comp, import_path)
        File "/Users/jzeller/buildapi-test/lib/python2.7/site-packages/mock.py", line 1089, in _dot_lookup
          return getattr(thing, comp)
        File "/Users/jzeller/buildapi-test/lib/python2.7/site-packages/paste/registry.py", line 137, in __getattr__
          return getattr(self._current_obj(), attr)
        File "/Users/jzeller/buildapi-test/lib/python2.7/site-packages/paste/registry.py", line 197, in _current_obj
          'thread' % self.____name__)
      TypeError: No object (name: app_globals) has been registered for this thread
      
      >>> from buildapi.controllers.selfserve import SelfserveController
      >>> from mock import patch, Mock
      
      >>> s = SelfserveController()
      >>> s._ok = Mock(name='_ok')
      >>> s._get_stable_delay = Mock(return_value=180)
      >>> s._branches_cache = Mock()
      >>> s._branches_cache = {'try': None}
      >>> s._failed = Mock(return_value="Failed")
      >>> g = Mock()
      >>> g.buildapi_cache = Mock(name='buildapi_cache')
      >>> g.buildapi_cache.get_builds_for_revision = Mock(name='get_builds_for_revision', return_value=['baz', 'bang'])
      >>> s.revision('try', 'bar')
      Traceback (most recent call last):
        File "<stdin>", line 1, in <module>
        File "buildapi/controllers/selfserve.py", line 217, in revision
          job_items = g.buildapi_cache.get_builds_for_revision(branch, revision)
        File "/Users/jzeller/buildapi-test/lib/python2.7/site-packages/paste/registry.py", line 137, in __getattr__
          return getattr(self._current_obj(), attr)
        File "/Users/jzeller/buildapi-test/lib/python2.7/site-packages/paste/registry.py", line 197, in _current_obj
          'thread' % self.____name__)
      TypeError: No object (name: app_globals) has been registered for this thread