简体   繁体   English

Pytest:如何调用夹具的补丁

[英]Pytest: How to call the patch of a fixture

pytest 5.0.1 python 3.6 pytest 5.0.1 python 3.6

Imagine that you have a class that you import and initialize in another class想象一下,您有一个 class 导入并在另一个 class 中初始化

from file import Client
class A()

    def __init__(self):
        self.client = Client()

    def call(self):
        self.client.execute()

Now when I want to test it, because this import class touches outside components (eg a database), I want to mock the thing from happening (eg I can't believe you read databases so slowly...).现在当我想测试它时,因为这个导入 class 涉及外部组件(例如数据库),我想模拟事情的发生(例如,我不敢相信你读数据库这么慢......)。 But for reals.但实事求是。 So I have a fixture with a patch in it.所以我有一个带有补丁的夹具。 Yay!耶!

 @pytest.fixture
 def setup_a(self):
    with patch('path_to_patch') as patched:
        a = A()
    return a

However, I can't seem to get the patch out of the fxiture to use it.但是,我似乎无法从 fxiture 中取出补丁来使用它。 I've tried creating a new patch, but this doesn't work (eg assert False)我尝试创建一个新补丁,但这不起作用(例如断言 False)

@patch('path_to_patch')
def test_successful_execution(self, new_patch, setup_a):
    setup_a.call()
    assert new_patch.execute.called

I've also tried using the above patch implicitly我也尝试过隐式使用上述补丁

@patch('path_to_patch')
def test_successful_execution(self, new_patch, setup_a):
    setup_a.call()
    assert setup_a.execute.called    

What is the right way to do this?这样做的正确方法是什么? Let me know if you need more of an explanation.如果您需要更多解释,请告诉我。

I assume you want to patch Client.execute in A , and the fixture shall return an object of type A with that patch in place.我假设您想在A中修补Client.execute ,并且夹具应返回A类型的 object 并带有该补丁。 The first thing is to make sure that the patching is still active:首先要确保补丁仍然处于活动状态:

 @pytest.fixture
 def mocked_a(self):
     with patch('path_to_a.Client.execute'):
         yield A()

In your example you had the object returned after the patching scope, meaning the patching had already ended at that point.在您的示例中,您在修补 scope 后返回了 object,这意味着修补此时已经结束。 Also note that you have to patch the Client module as imported in the a module (assuming that is where A is defined).另请注意,您必须修补在a模块中导入的Client模块(假设这是定义A的位置)。

To use the patched object, you can now:要使用已修补的 object,您现在可以:

def test_successful_execution(mocked_a):
    mocked_a.call()
    mocked_a.Client.execute.assert_called_once()

Note that you can access the mock the same way you mocked it.请注意,您可以像模拟它一样访问模拟。

Alternatively, you can return the mock itself in the fixture:或者,您可以在夹具中返回模拟本身:

 @pytest.fixture
 def mocked_execute(self):
     with patch('path_to_a.Client.execute') as patched:
         yield patched

def test_successful_execution(mocked_execute):
    a = A()
    a.call()
    mocked_execute.assert_called_once()

This way you explicitely create the object in your test, and the test is more clear, in my opinion.这样,您可以在测试中明确创建 object,并且在我看来,测试更加清晰。

(this is out of my head, so there may be errors...) (这不是我的想法,所以可能会有错误......)

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

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