Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/google-apps-script/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python unittest黑名单名称空间,任何引用它的尝试都失败_Python_Unit Testing_Python Unittest_Isolation - Fatal编程技术网

Python unittest黑名单名称空间,任何引用它的尝试都失败

Python unittest黑名单名称空间,任何引用它的尝试都失败,python,unit-testing,python-unittest,isolation,Python,Unit Testing,Python Unittest,Isolation,在单元测试包装器库的情况下,在不依赖/使用上游库的情况下测试包装器是一个目标;在已知的情况下,对上游库的所有调用都可以模拟,这就是我所做的,但我对包装器的更改感到失望,因为这些更改会导致模拟工具错过更多对上游库的调用 我怎样才能最好地通过任何试图使用给定名称空间的测试 我现在的想法是改变所有的unittest方法,让它有一个像猴子一样的补丁 @unittest.mock.patch('wrapper_namespace.upsteam_namespace') 并用一个可以断言为未触及的mock

在单元测试包装器库的情况下,在不依赖/使用上游库的情况下测试包装器是一个目标;在已知的情况下,对上游库的所有调用都可以模拟,这就是我所做的,但我对包装器的更改感到失望,因为这些更改会导致模拟工具错过更多对上游库的调用

我怎样才能最好地通过任何试图使用给定名称空间的测试

我现在的想法是改变所有的unittest方法,让它有一个像猴子一样的补丁

@unittest.mock.patch('wrapper_namespace.upsteam_namespace')
并用一个可以断言为未触及的mock来回复上游库;我希望有一个全球性的选择,这样我

  • 不必为每个测试方法添加monkeypatch,尽管这种粒度级别是可以接受的;但是也不必执行mock从未在测试方法中使用过的断言(或者让一个decorator来完成这一切)
  • 禁止从软件的任何部分访问上游库 (例如,包装器调用B向上游调用,B向上游调用可能未被捕获)

    • 您不必修补每种测试方法。如果您使用的是
      unittest
      ,您可以轻松地修补
      ,或者只需将模块分配给您想要修补的任何模块即可。下面是一个可行的例子:

      某些_lib.py中的假库:

      def some_lib_func():
          raise ValueError("I've been called.")
      
      def some_other_lib_func():
          raise ValueError("I've been called.")
      
      class SomeClass:
          def __init__(self):
              raise ValueError("I've been constructed.")
      
      wrapper.py:

      import some_lib
      
      def wrapper1():
          some_lib.some_lib_func()
      
      def wrapper2():
          some_lib.some_other_lib_func()
      
      def wrapper3():
          x = some_lib.SomeClass()
      
      test.py:

      from unittest.mock import patch, MagicMock
      import unittest
      
      import wrapper
      
      # Alternative:                                                                                                                                            
      # wrapper.some_lib = MagicMock()                                                                                                                                                                            
      
      # Can patch an entire class                                                                                                                                                                                 
      @patch('wrapper.some_lib', MagicMock())
      class TestWrapper(unittest.TestCase):
          def test_wrapper1(self):
              wrapper.wrapper1()
      
          def test_wrapper2(self):
              wrapper.wrapper2()
      
          def test_wrapper3(self):
              wrapper.wrapper3()
      
      if __name__ == "__main__":
          unittest.main()
      
      如果调用了
      some_lib
      中的函数/类,但它们不是:

      Matthews-MacBook-Pro:stackoverflow matt$ python test.py
      ...
      ----------------------------------------------------------------------
      Ran 3 tests in 0.001s
      
      OK
      
      请随意对补丁进行注释,并在
      wrapper.some_lib=MagicMock()
      中进行注释。在这个玩具示例中,您将得到相同的结果,但这两种方法之间有一个主要区别:

      使用
      @patch('wrapper.some_lib',MagicMock())时
      该补丁仅针对该测试用例类有效。

      但是,当使用
      wrapper.some_lib=MagicMock()
      时,该修补程序将在python程序的整个过程中保持有效,除非您保存原始模块并在某个时间手动将其修补回来。使用
      包装器
      模块的所有内容都将获得模拟版本

      所以你可以这样说:

      original_lib = wrapper.some_lib
      wrapper.some_lib = MagicMock()
      ...
      # call some test suite, every call to the wrapper module will be mocked out
      ...
      wrapper.some_lib = original_lib
      ...
      # call some other test suite that actually needs the real thing
      ...
      


      EDIT:稍微误读您的问题,但您可以检查
      MagicMock
      对象,查看它们是否已被调用,如果是,则测试失败。或者只是用调用时失败的东西进行修补(而不是
      MagicMock
      )。如果需要,我可以提供代码来完成这项工作(只需留下评论),但希望上面的内容可以帮助您开始。我认为问题的关键其实是全球修补。干杯

      如果您可以通过检查相关对象自动完成所有工作,那么选项1听起来并不太糟糕。关于选项2,您能否将上游封装在一个监视/管理属性访问的附加对象中?也许一个小小的例子会有助于更好地了解你的处境。