Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/301.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/unit-testing/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python mock-修改类属性的mock类方法_Python_Unit Testing_Mocking_Python Unittest.mock_Pytest Mock - Fatal编程技术网

Python mock-修改类属性的mock类方法

Python mock-修改类属性的mock类方法,python,unit-testing,mocking,python-unittest.mock,pytest-mock,Python,Unit Testing,Mocking,Python Unittest.mock,Pytest Mock,我目前有以下要测试的基本Python类: class Example: def run_steps(self): self.steps = 0 while self.steps < 4: self.step() def step(self): # some expensive API call print("wasting time...")

我目前有以下要测试的基本Python类:

class Example:

    def run_steps(self):
        self.steps = 0

        while self.steps < 4:
            self.step()
    
    def step(self):
        # some expensive API call
        print("wasting time...")
        time.sleep(1000)

        self.steps += 1
我只需创建一个名为
mock\u-step(self)
的函数,以避免API调用,并使用新的
mock\u-step(self)
函数修补原始的慢速
step()
方法

然而,这带来了一个新问题。由于
mock\u步骤(self)
函数不是一个mock对象,因此我无法对其调用任何mock方法(例如assert\u called()和call\u count()):

为了解决这个问题,我尝试使用
wrapps
参数用模拟对象包装
mock\u步骤

def test(mocker):
    example = Example()

    # this doesn't work
    step = mocker.Mock(wraps=mock_step)
    mocker.patch.object(Example, 'step', step)

    example.run_steps()

    assert step.call_count == 4
但是我得到一个不同的错误,说
mock_step()缺少一个必需的位置参数:“self”


因此,从这个阶段开始,我不确定如何断言
step()
run\u steps()

中被精确调用了4次。对此,有几种解决方案,最简单的可能是使用带有副作用的标准模拟:

def mock_步骤(自):
打印(“跳过浪费时间”)
self.steps+=1
def测试步骤(模拟程序):
示例=示例()
mocked=mocker.patch.object(例如,“步骤”)
mocked.side_effect=lambda:mock_步骤(示例)
示例。运行_步骤()
断言mocked.call\u count==4
side\u effect
可以调用,因此您可以使用标准mock和补丁方法。

import unittest.mock as mock
从functools导入部分
def fake_步骤(自):
打印(“伪造”)
self.steps+=1
def test_api():
api=示例()
使用mock.patch.object(api,attribute=“step”,new=partial(fake\u step,self=api)):
#我们需要使用'partial'来模拟实际方法在实例化时绑定了'self'参数
api.run_步骤()
断言api.steps==4

正确输出
“伪造的”
4次。

我用
导入模拟
测试了您的解决方案,而不是注入
模拟
。但是您似乎修补了类对方法的定义,而不是绑定到对象的实际方法,这导致调用浪费时间的代码。@Lenormju-好吧,我按原样测试了代码,它对我有效(例如,不调用生产代码)。我使用mocker是因为问题使用了它,而且使用
pytest
更方便。我还想允许使用标准的
mock
来允许
call\u count
assert\u call\u xxx
等。而不是自己进行计数(当然,这也是一个解决方案)。你是对的,我没有注意到它出现在OP的代码中,我只需要
pip安装pytest mock
,它就工作了。你的解决方案比我的好:)谢谢,这对我很有效。我不知道
mocker.patch
返回了一个补丁对象的Mock,所以我从来没有想过要执行类似
mocked=mocker.patch.object的操作(例如,“步骤”)
。谢谢你的帮助:)
def test(mocker):
    example = Example()
    mocker.patch.object(Example, 'step', mock_step)

    example.run_steps()

    # this line doesn't work
    assert mock_step.call_count == 4
def test(mocker):
    example = Example()

    # this doesn't work
    step = mocker.Mock(wraps=mock_step)
    mocker.patch.object(Example, 'step', step)

    example.run_steps()

    assert step.call_count == 4