简体   繁体   English

pytest 在 class 的 __init__ 中模拟 function 调用

[英]pytest mock a function call in __init__ of a class

I have a class like this,我有一个像这样的 class,

from external_package.module.sub_module import fun

class MyClass:
    def __init__(self, x, y):
        self.x = x
        self.y = y
        self.z = fun()
        
    def printer(self):
        print(f"X : {self.x}, y : {self.y}, z: {self.z}")

I want to write a unit test for this class and mock the function call that is happening in the init method.我想为此 class 编写一个单元测试并模拟在init方法中发生的 function 调用。

I have tried patching like this,我试过这样打补丁,

from external_package.module import sub_module
    
def test_my_class(mocker):

    mocker.patch.object(sub_module, 'fun', return_value="this is mocked")
    obj = MyClass(10, 20)
    
    assert obj.z == "this is mocked"

But I can see that the call is not patched and a function call happens in the init method.但我可以看到该调用未修补,并且在init方法中发生了 function 调用。

How can I patch the call with pytest-mock or any other mocking packages?如何使用 pytest-mock 或任何其他 mocking 软件包修补呼叫?

You should mock your function with the path where it's been used and not it's original path or location.您应该使用使用它的路径而不是原始路径或位置来模拟您的 function。 In the example bellows it's defined that the fun method in the object MyClass will be mocked and the returned value will be "this is mocked".在下面的示例中,定义了 object MyClass 中的 fun 方法将被模拟,返回值将是“this is mocked”。

from external_package.module import sub_module
from my_class import MyClass

def test_my_class(mocker):

    mocker.patch.object(MyClass.submodule, 'fun', return_value="this is mocked")
    obj = MyClass(10, 20)
    
    assert obj.z == "this is mocked"

Check this link for some good examples of how to mock objects in Python.查看此链接,了解如何在 Python 中模拟对象的一些很好的示例。

I was able to solve this by slightly changing the import statement in the source code,我可以通过稍微更改源代码中的导入语句来解决这个问题,

from external_package.module import sub_module 

class MyClass:
    def __init__(self, x, y):
        self.x = x
        self.y = y
        self.z = sub_module.fun()
        
    def printer(self):
        print(f"X : {self.x}, y : {self.y}, z: {self.z}")

Note that I'm importing submodule and calling method from the imported sub_module.请注意,我正在导入子模块并从导入的 sub_module 调用方法。

Now, in the test I used the pytest-mock fixture like this,现在,在测试中,我像这样使用了pytest-mock夹具,

import external_package
    
def test_my_class(mocker):

    method = mocker.patch("external_package.module.sub_module.fun")
    method.return_value = "this is mocked"

    obj = MyClass(10, 20)
    
    assert obj.z == "this is mocked"

I'm not sure why this worked and not the earlier approach.我不确定为什么这有效,而不是早期的方法。 Hope someone can clear that.希望有人能澄清这一点。

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

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