如何在Python中模拟实例方法

问题描述 投票:0回答:1

请考虑以下三个文件。

# my_class.py

class MyClass:
    def __init__(self):
        pass

    def do_thing(self):
        return 5


# main.py

from my_class import MyClass

def my_func():
    instance = MyClass()
    instance.do_thing()


# test_main.py

from main import my_func
from unittest.mock import patch

@patch('main.MyClass')
def test_my_func(MockMyClass):
    my_func()
    MockMyClass.do_thing.assert_called_once()

AssertionError: Expected 'do_thing' to have been called once. Called 0 times.

我正在驱动程序函数MyClass中实例化一个类my_func,并调用该类的方法之一do_thing。我想做的是测试在调用驱动程序函数时,该类的方法仅被调用一次。我遇到断言错误,这给我带来了问题。

我已经在线阅读了一百万篇关于Python模拟的SO帖子和其他资源,但是我无法弄清楚。我认为诀窍是@patch装饰器修补了模块导入到的名称空间,而不是从[Python Mocking a function from an imported module。我在这里错了吗?

python mocking pytest python-unittest
1个回答
0
投票

do_thing方法是MyClassNOT类方法的实例方法。您断言MockMyClass.do_thing.assert_called_once()不正确。这是单元测试解决方案:

my_class.py

class MyClass:
    def __init__(self):
        pass

    def do_thing(self):
        return 5

main.py


from my_class import MyClass


def my_func():
    instance = MyClass()
    instance.do_thing()

test_main.py

from main import my_func
import unittest
from unittest.mock import patch


class TestMain(unittest.TestCase):
    @patch('main.MyClass')
    def test_my_func(self, MockMyClass):
        mock_my_class_instance = MockMyClass.return_value
        my_func()
        mock_my_class_instance.do_thing.assert_called_once()


if __name__ == '__main__':
    unittest.main()

带有覆盖率报告的单元测试结果:

.
----------------------------------------------------------------------
Ran 1 test in 0.001s

OK
Name                                      Stmts   Miss  Cover   Missing
-----------------------------------------------------------------------
src/stackoverflow/60539392/main.py            4      0   100%
src/stackoverflow/60539392/my_class.py        5      2    60%   3, 6
src/stackoverflow/60539392/test_main.py      10      0   100%
-----------------------------------------------------------------------
TOTAL
© www.soinside.com 2019 - 2024. All rights reserved.