繁体   English   中英

您如何模拟 Python 中测试方法的输入?

[英]How do you mock inputs to methods for testing in Python?

我希望在 Python 中测试一些代码 - 特别是 class 方法。

我有一个 class 看起来像

class BigBoyClass:
   def __init__(self, ...{configuration objects}...):
       ...{expensive init}...
       self.init_attr1 = ...
       self.init_attr2 = ...

   def method1(self):
      self.new_attr1 = ...
      self.new_attr2 = ...

要测试method1我想通过init_attr1init_attr2具有特定值的“ self

到目前为止,我一直在做:

class DummyContainer:
    def __init__(self):
       pass

c = DummyContainer()
c.init_attr1 = {v1}
c.init_attr2 = {v2}

BigBoyClass.method1(c)

assert c.new_attr1 == {v3}
assert c.new_attr2 == {v4}

但我觉得我在这里重新发明了轮子。 有一个更好的方法吗?

的确。 如果你可以重构BigBoyClass.__init__方法,你可以做得比模拟更好!

根据您的示例,这是我的初始情况:

class BigBoyClass:
   def __init__(self, big_number: int):
       sum(range(big_number))  # something slow
       self.init_attr1 = big_number  # whatever
       self.init_attr2 = big_number + 1  # whatever

   def method1(self):
      self.new_attr1 = 4  # whatever
      self.new_attr2 = 5  # whatever


def test_method1():
    # given
    instance = BigBoyClass(10**9)  # takes a few seconds on my computer

    # when
    instance.method1()

    # then
    assert (instance.new_attr1 == 4) and (instance.new_attr2 == 5)

我想要的是一个愚蠢__init__ :它被赋予了参数,它只是将它们设置为相应的self字段。 复杂部分被classmethod到将处理复杂部分的类方法。

class BigBoyClass:
    def __init__(self, attr1: int, attr2: int):
        # removed the slow part here
        self.init_attr1 = attr1
        self.init_attr2 = attr2

    def method1(self):
        self.new_attr1 = 4  # whatever
        self.new_attr2 = 5  # whatever

    @classmethod
    def init_with_config_object(cls, big_number: int):
        sum(range(big_number))  # something slow
        return cls(big_number, big_number+1)


def test_method1():
    # given
    instance = BigBoyClass(10**9, 10**9+1)  # lightning-fast !

    # when
    instance.method1()

    # then
    assert (instance.new_attr1 == 4) and (instance.new_attr2 == 5)

我根本没有更改我的测试,但是因为我更改了__init__签名,所以现在我必须调整BigBoy class 的所有其他现有实例,以调用init_with_config_object而不仅仅是 class 本身。

你这样做的好处是:

  • 无需模拟,因此编写测试更容易
  • 没有模拟,因此当您的实际 class 更改时,您不必维护它们
  • 您可以单独检查配置是否正确初始化,以及该方法是否符合预期
  • 如果您需要能够以不同的方式实例化相同的 class,您可以添加其他类方法
  • 如果为您的init_attr的 init_attr 提供值很复杂,您可以创建测试工厂:为您处理的函数,无论如何直接调用__init__

我不知道这种技术是否有名字,但它看起来有点像“java bean” ,因为它提供了以任何方式构造的方式,对签名/协议没有限制。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM