我认为打补丁的正确方法是模拟Python类,然后在打补丁的类上调用.return_value,但我不确定为什么.假设我有一些代码:

Class.py:

class SomeClass:
  def __init__(self, some_value):
    self.some_value = some_value

  def add_to_value(self, add_value):
    self.some_value = self.some_value + add_value

Function_thing.py:

from my_pkg.class import SomeClass

def some_function():
    some_class_instance = SomeClass(5)
    some_class_instance.add_to_value(6)

test_Function_thing.py:

from my_pkg.function_thing import some_function
class TestSomeFunction(TestCase)
  # This works, and it knows the function was called with 6
  @patch("my_pkg.function_thing.SomeClass")
  def test_some_function_01(self, mock_some_class):
    instance_mock = mock_some_class.return_value
    some_function()
    instance_mock.add_to_value.assert_called_with(6)

  # This does not work.
  @patch("my_pkg.function_thing.SomeClass.add_to_value")
  def test_some_function_02(self, mock_add_to_value):
    some_function()
    # This succeeds.
    mock_add_to_value.assert_called_once()
    # This fails, saying it wasn't called with 6 but some object
    mock_add_to_value.assert_called_with(6)

似乎,为了让模拟正确理解类是如何调用的,我们不能将函数作为一个整体来模拟.但我们可以断言该函数已被调用.我认为,要么断言函数被调用会失败,要么断言函数是如何调用的,或者两个都会成功.谢谢您提供的信息!

推荐答案

这是因为SomeClass.add_to_value有两个参数:selfadd_value.

def add_to_value(self, add_value):

尽管Python语法允许您在调用时魔术般地消除self参数,但就Python而言,它仍然存在.所以您已经断言,该方法是使用参数元组(6,)调用的,而实际上它是使用参数元组(whatever, 6)调用的,其中whatever是由some_function生成的实例.

现在,我们could继续嘲笑,就像您在示例中所做的那样.但我们或许该停下来了.如果您发现需要模拟一半的代码库来测试一个函数,这是一个很好的迹象,表明该函数正在进行lot个假设,应该与其他所有函数分离.在本例中,您可以将一个SomeClass实例传递给some_function

def some_function(some_class_instance=None):
    if some_class_instance is None:
        some_class_instance = SomeClass(5)
    some_class_instance.add_to_value(6)

现在,现有的调用方仍然使用"不错的"缺省值,但是测试(和其他用户)可以使用他们 Select 的任何实例来调用该函数.

您也可以在工厂级别进行注入,将工厂传递给一个类.

def some_function(class_to_instantiate=SomeClass):
    some_class_instance = class_to_instantiate(5)
    some_class_instance.add_to_value(6)

现在,您可以将class_to_instantiate参数更改为您完全控制的类,以便对其进行测试.

Python相关问答推荐

使用itertools出现第n个子串

Numpy索引argsorted使用integer数组,同时保留排序顺序

由于瓶颈,Python代码执行太慢-寻求性能优化

Python中是否有方法从公共域检索搜索结果

在应用循环中间保存pandas DataFrame

如何使用没有Selenium的Python在百思买着陆页面上处理国家/地区 Select ?

计算所有前面行(当前行)中列的值

将HLS纳入媒体包

根据给定日期的状态过滤查询集

使用Keras的线性回归参数估计

Polars比较了两个预设-有没有方法在第一次不匹配时立即失败

将jit与numpy linSpace函数一起使用时出错

如何让剧作家等待Python中出现特定cookie(然后返回它)?

如何使用LangChain和AzureOpenAI在Python中解决AttribeHelp和BadPressMessage错误?

如何在Python中并行化以下搜索?

我如何使法国在 map 中完全透明的代码?

将输入聚合到统一词典中

如何使Matplotlib标题以图形为中心,而图例框则以图形为中心

使用特定值作为引用替换数据框行上的值

未调用自定义JSON编码器