使用函数模拟类的方法返回值

时间:2018-11-23 09:32:07

标签: python testing

模拟和尝试使用side_effects是我的新手。

我试图基于调用该方法的参数来设置模拟类方法的返回值。在下面的代码中,当尝试模拟some_function时,我试图设置MyClass的返回值。

# application.py
from my_module.my_submodule import MyClass

def my_function(var1):
    instance = MyClass()

    instance.some_function(var1)

和我的测试文件

# test_application.py
import mock
import application

def test_my_function():
    with mock.patch('application.MyClass') as MockClass:
        MockClass.return_value.my_function.return_value = some_return

        application.my_function(var1)

这样工作,使得some_function现在返回some_return,但是我希望有一个函数代替some_return,该函数采用参数var1,该函数被调用用。

问题是我不知道如何定义模拟来预测some_function的调用参数。

我已经尝试了本文changing the side effect of a mock object's method created with patch中讨论的内容,但是我一生都无法弄清楚如何格式化它。

我已经尝试过类似的事情

# test_application.py
import mock
import application

def test_my_function():
    with mock.patch('application.MyClass') as MockClass:
        MockClass.return_value.my_function.return_value = some_return  

        # Breaking very long line, in my code it's actually one line.
        MockDataPrep.return_value.extract_preprocessed_citizen_data.\
        side_effect =\
        mock.MagicMock(side_effect=my_side_effect)

        application.my_function(var1)

函数my_side_effect如下所示:

def my_side_effect(var1):
    return_val = some_manipulation_of_var1(var1)

    if something:
        return `abc`
    else:
        raise LookupError

,但是似乎从未输入过my_side_effect(尝试使用其中的打印语句)。我该如何格式化?

2 个答案:

答案 0 :(得分:1)

您在嘲笑错误的方法。 my_functionapplication模块的功能,而不是MyClass的方法,因此,您要模拟的是some_function

import mock
import application


def my_side_effect(*args, **kwargs):
    print("my_side_effect called")
    print(args, kwargs)


def test_my_function():
    with mock.patch("application.MyClass") as MockClass:
        MockClass.return_value.some_function.side_effect = my_side_effect

        application.my_function(arg1)

通过这种方式,arg1将被传递到my_side_effect中的*args

此外,您可能只想模拟一个特定的方法,而不是整个类。

def test_my_function():
    with mock.patch("application.MyClass.some_function") as mock_some_function:
        mock_some_function.side_effect = my_side_effect

        application.my_function(arg1)

答案 1 :(得分:0)

您似乎转向side_effects是因为您无法使用return_value

但是您可以使用wraps模拟参数。它用mock包装一个对象。您只能在对象中使用现有方法(尽管您可以添加更多方法),并且返回的结果是实际方法执行的结果。 return_value被忽略:

from unittest.mock import Mock

class Mirror:
    def func(self,x):
        return x

mirror = Mirror()
m = Mock(wraps=mirror)
print(m.func(20))

如果相反,您想测试如何调用模拟程序,使用什么args,多少次,等等,那么模拟对象中也有检查方法。