unittest blacklist namespace 并且任何引用它的尝试都失败

unittest blacklist namespace and fail any attempt to reference it

在对包装器库进行单元测试的情况下,在没有 depending/exercising 上游库的情况下测试包装器是一个目标;在一个已知的案例中,所有对上游库的调用都可以被模拟,这就是我所做的,但我对包装器的更改感到沮丧,这些更改引入了对上游库的更多调用被模拟工具错过;

我怎样才能最好地让任何尝试使用给定名称空间的测试失败?

我目前的想法是改变所有的单元测试方法来拥有像

这样的猴子补丁
@unittest.mock.patch('wrapper_namespace.upsteam_namespace')

并用一个可以断言不受影响的模拟回复上游库;我希望有一个全球通用的选项,这样我

您不必为每个测试方法都打补丁。如果您正在使用 unittest,您可以轻松地修补 class,或者只需将模块分配给您想要修补它的任何内容。这是一个可行的例子:

some_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 中的 functions/classes 被调用,我们会爆炸,但它们不是:

Matthews-MacBook-Pro:Whosebug matt$ python test.py
...
----------------------------------------------------------------------
Ran 3 tests in 0.001s

OK

欢迎在 wrapper.some_lib = MagicMock() 中评论补丁和评论。在这个玩具示例中,您会得到相同的结果,但两种方法之间存在重大差异:

使用@patch('wrapper.some_lib', MagicMock())补丁仅适用于该测试用例class.

但是,当使用 wrapper.some_lib = MagicMock() 时,该补丁将在 整个 python 程序,除非您保存原始模块并在某个时候手动修补它。使用 wrapper 模块的所有内容都将获得模拟版本。

所以你可以这样:

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
...

HTH.

编辑: 稍微误读了您的问题,但您可以检查 MagicMock 对象以查看它们是否已被调用,如果已调用,则测试失败。或者只是用调用时失败的东西来修补(而不是 MagicMock)。如果需要,我可以提供代码来执行此操作(只需发表评论),但希望以上内容可以帮助您入门。我认为问题的症结在于全局补丁。干杯!