简体   繁体   English

unittest.mock.patch:上下文管理器vs unittest中的setUp / tearDown

[英]unittest.mock.patch: Context manager vs setUp/tearDown in unittest

There seems to be 2 ways to use unittest.mock.patch : is one way better? 似乎有两种使用unittest.mock.patch的方法 :一种更好的方法吗?

Using a context manager and with statement: 使用上下文管理器和with语句:

class MyTest(TestCase):
    def test_something(self):
        with patch('package.module.Class') as MockClass:
            assert package.module.Class is MockClass

Or calling start and stop from setup and tearDown/cleanup: 或从设置和tearDown / cleanup调用启动和停止:

class MyTest(TestCase):
    def setUp(self):
        patcher = patch('package.module.Class')
        self.MockClass = patcher.start()
        self.addCleanup(patcher.stop)

    def test_something(self):
        assert package.module.Class is self.MockClass

The context manager version is less code, and so arguable easier to read. 上下文管理器版本的代码较少,因此易于争论。 I there any reason why I should prefer to use the TestCase setUp/tearDown infrastructure? 我有什么理由偏爱使用TestCase setUp / tearDown基础结构吗?

The main reason to prefer patching in the setUp would be if you had more than one test that needed that class patched. setUp更喜欢修补的主要原因是,如果您有多个需要对该类进行修补的测试。 In that case, you'd need to duplicate the with statement in each test. 在这种情况下,您需要在每个测试中复制with语句。

If you only have one test that needs the patch, I'd prefer the with statement for readability. 如果您只有一个需要补丁的测试,那么我宁愿使用with语句以提高可读性。

There is yet a third way to use it, as a decorator: 还有第三种使用它的方法,作为装饰器:

class MyTest(testcase):

    @unittest.mock.patch('package.module.Class')
    def test_something(self):
        assert package.module.Class is self.MockClass

This is even less code, but that may not be relevant. 这甚至是更少的代码,但是可能不相关。

There are a few considerations: (1) (as pointed out by babbageclunk) if you will need to reuse the patch, then a plain, boring call to construct one in setUp is best, and is easily readable. 有一些注意事项:(1)(如babbageclunk所指出),如果您将需要重用补丁,那么在setUp构造一个简单而乏味的调用是最好的,并且易于阅读。 (2) if you want to create any metaprogramming facilities so that you can turn on or off the patching when you run tests, then the decorator approach will save you a lot of trouble. (2)如果您想创建任何元编程工具,以便在运行测试时可以打开或关闭修补程序,那么装饰器方法将为您省去很多麻烦。 In that case, you can write an additional decorator, or use a global variable (ick) to control whether the patch decorators get applied to the test functions or not. 在这种情况下,您可以编写其他修饰符,或使用全局变量(ick)控制是否将补丁修饰符应用于测试功能。 If they are embedded inside the function definitions, then you have to manually deal with them if you ever want to turn off patching when running tests. 如果它们嵌入在函数定义中,则如果要在运行测试时关闭修补程序,则必须手动处理它们。 One simple reason why you might want this is merely to run the tests with no patching to induce lots of failures and observe which pieces you have not implemented yet (your decorator for metaprogramming the patches, in fact, could catch these issues and print nice NotImplemented exceptions for you, or even generate a report containing such things). 您可能希望这样做的一个简单原因只是在没有补丁的情况下运行测试,从而导致大量失败,并观察尚未实现的部分(实际上,您用于元编程补丁的装饰器可能会捕获这些问题并打印出不错的NotImplemented例外,甚至生成包含此类内容的报告)。 There could be many more reasons to want fine control over whether (and to what degree) patching is "dispatched" in the test suite at a given time. 可能有更多的原因想要更好地控制在给定时间在测试套件中是否(以及在何种程度上)修补程序被“分发”。

The decorator approach is also nice in that (a) it lets you isolate which patches go to which test functions in a manner that is outside of that function, but without committing it to setUp , and (b) it makes it very clear to the reader when a given function requires a given patch. 装饰器方法也很不错,因为(a)它允许您以该函数之外的方式隔离哪些补丁进入了哪个测试函数,而无需将其提交给setUp ;以及(b)使其非常清楚给定功能需要给定补丁的阅读器。

The context manager version does not seem to have many benefits in this case since it is hardly more readable than the decorator version. 在这种情况下,上下文管理器版本似乎没有很多好处,因为它几乎不比装饰器版本更具可读性。 But, if there really is only a single case, or a very small set of specific cases, where this is used, then the context manager version would be perfectly fine. 但是,如果确实只使用一种情况,或者使用的情况很少,那么上下文管理器版本就可以了。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM