简体   繁体   English

如何在 Python 中模拟实例方法

[英]How to mock an instance method in Python

I'm trying to test a class and mock one of its methods, but I can't seem to replace the behavior of one of the instance methods with my mocked behavior.我正在尝试测试一个类并模拟它的一个方法,但我似乎无法用我的模拟行为替换其中一个实例方法的行为。 My code is organized like so:我的代码是这样组织的:

--src ----module ------__init__.py ------my_class.py --tst ----__init__.py ----test_my_class.py

my_class.py contains the following my_class.py包含以下内容

class MyClass:

    def __init__(self):
        pass

    def do_something(self):
        return 'Real Output'

My test file test_my_class.py contains the following.我的测试文件test_my_class.py包含以下内容。

from unittest.mock import patch
from src.module.my_class import MyClass

def test_my_class():
    my_class = MyClass()
    assert my_class.do_something() == 'Real Output'

@patch('src.module.my_class.MyClass')
def test_mock_my_class(mock_my_class):
    mock_my_class.return_value.do_something.return_value = 'Mocked Output'
    my_class = MyClass()
    assert my_class.do_something() == 'Mocked Output'

The first test works just fine (no mocking involved so far).第一个测试工作得很好(到目前为止不涉及嘲笑)。 The second test, however, gives me the following assertion error.然而,第二个测试给了我以下断言错误。 I expect the do_something() method to be mocked and to return "Mocked Output", and for the assert statement to evaluate to true.我希望do_something()方法被模拟并返回“模拟输出”,并且断言语句评估为真。 Where am I going wrong here?我在哪里错了?

AssertionError: assert <bound method MyClass.do_something of <src.module.my_class.MyClass object at 0x1057133c8>> == 'Mocked Output' E + where <bound method MyClass.do_something of <src.module.my_class.MyClass object at 0x1057133c8>> = <src.module.my_class.MyClass object at 0x1057133c8>.do_something

PS. PS。 I've consulted the following resources without success:我咨询了以下资源但没有成功:

That last link looked especially helpful at first, because I'm following one of the examples almost verbatim, but it still doesn't work.最后一个链接起初看起来特别有用,因为我几乎逐字逐句地遵循其中一个示例,但它仍然不起作用。

@mock.patch("simple.SimpleClass")
def mock_simple_class(mock_class):
    mock_class.return_value.explode.return_value = "BOO!"
    inst = simple.SimpleClass()
    result = inst.explode()
    print(result)

A more appropriate way to solve this is to use patch.object解决这个问题的更合适的方法是使用 patch.object

@patch.object(MyClass, "do_something")
def test_mock_my_class(m):
    m.side_effect = ['Mocked Output']
    my_class = MyClass()
    assert my_class.do_something() == 'Mocked Output'

Personally, patch.object confuses me.就个人而言, patch.object让我感到困惑。 After reading this article , I have decided to stick with patch only.读完这篇文章后,我决定只使用patch

The problem with the patch in the question is that the MyClass patched is not the MyClass used in the test function.问题中patch的问题在于,打补丁的MyClass不是test函数中使用的MyClass Refer to this guide for a more in-depth explanation of where patch should be applied.有关应在何处应用补丁的更深入说明,请参阅本指南

The path of the patch should be tst.test_my_class.MyClass , as shown in the code below.补丁的路径应该是tst.test_my_class.MyClass ,如下面的代码所示。

from unittest.mock import patch
import unittest
from src.module.my_class import MyClass


class Test(unittest.TestCase):
    def test_my_class(self):
        my_class = MyClass()
        self.assertTrue(my_class.do_something() == 'Real Output')

    @patch('test.test_my_class.MyClass')
    def test_mock_my_class(self, mock_my_class):
        mock_my_class.return_value.do_something.return_value = 'Mocked Output'
        my_class = MyClass()
        self.assertTrue(my_class.do_something() == 'Mocked Output')

Run this command to execute it in a terminal.运行此命令以在终端中执行它。

python3 -m unittest discover

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

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