修补Python类和Python类的方法有什么区别?

问题描述 投票:0回答:1

我相信正确的修补方法是模拟 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)

看来,为了让模拟正确理解类是如何被调用的,我们不能模拟整个函数。但我们可以断言该函数已被调用。我认为断言该函数被调用将会失败以及它的调用方式,或者两者都会成功。感谢您提供任何信息!

python python-unittest
1个回答
0
投票

那是因为

SomeClass.add_to_value
有两个参数:
self
add_value

def add_to_value(self, add_value):

尽管 Python 语法可以让你在调用时神奇地去掉

self
参数,但就 Python 而言,它仍然存在。因此,您断言该方法是使用参数元组
(6,)
调用的,而实际上它是使用参数元组
(whatever, 6)
调用的,其中
whatever
是由
some_function
生成的实例。

现在,我们可以继续嘲笑,就像你在例子中所做的那样。但我们或许应该停下来。如果您发现需要模拟一半的代码库来测试一个函数,那么这是一个很好的指标,表明该函数正在做出大量假设,并且应该与其他所有内容分离。在这种情况下,您可以将 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)

现在现有的调用者仍然获得“不错的”默认值,但测试(和其他用户)可以使用他们选择的任何实例来调用该函数。

您还可以在工厂级别注入,将工厂传递给一个类。

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

现在您可以将 
class_to_instantiate

参数更改为您可以完全控制的类以对其进行测试。

    

© www.soinside.com 2019 - 2024. All rights reserved.