【问题标题】:Use function for mocked class' method return value使用函数来模拟类的方法返回值
【发布时间】:2019-04-25 21:41:16
【问题描述】:

我不熟悉模拟并尝试使用副作用。

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

# 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(尝试使用其中的打印语句)。我将如何格式化?

【问题讨论】:

    标签: python testing


    【解决方案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 将在*args 内传递给my_side_effect

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

    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)
    

    【讨论】:

      【解决方案2】:

      看起来您转向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))
      

      如果你想测试一个 mock 是如何被调用的,用什么 args,多少次等等,mock 对象中也有检查方法。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2022-11-07
        • 2017-09-12
        • 1970-01-01
        • 1970-01-01
        • 2016-10-23
        • 1970-01-01
        • 2019-03-12
        • 1970-01-01
        相关资源
        最近更新 更多