gpt4 book ai didi

python - 如何模拟单例类方法

转载 作者:太空宇宙 更新时间:2023-11-04 08:50:49 29 4
gpt4 key购买 nike

假设我们有以下结构:

class A():
class __A():
def __to_be_mocked(self):
#something here
def __init__(self):
with A.lock:
if not A.instance:
A.instance = A.__A()

def __getattr__(self,name):
return getattr(self.instance,name)

现在我们要模拟函数__to_be_mocked。我们如何模拟它作为mock.patch.object接受的目标是package.module.ClassName 。我已经尝试了所有方法,例如

target = A.__A
target = A.___A

还有更多。

编辑:

我用

解决了它
target=A._A__A and attribute as '_A__to_be_mocked`

现在的问题是 __to_be_mocked__A 里面,所以它不应该是 ___A__to_be_mocked 吗。

是因为A中的setattribute还是A中的__init__

最佳答案

我在 python 中模拟了很多东西,在做了很多次之后我可以说:

  1. 从不 模拟/修补 __something 属性(又称 private 属性)
  2. 避免模拟/修补_something 属性(又名protected 属性)

私有(private)

如果您模拟私有(private)事物,您会混淆生产和测试代码。当您进行此类模拟时,总有一种方法可以通过修补或模拟公共(public)或 protected 内容来获得相同的行为。

为了更好地解释我所说的混淆生产代码和测试代码的意思,我可以使用您的示例:修补 A.__B.__to_be_mocked() (我替换了 __A 内部类通过 __B 使其更清楚)你需要写一些像

patch('amodule.A._A__B._B__to_be_mocked')

现在,通过修补 __to_be_mocked,您可以在测试中传播 ABto_be_mocked 名称:即正是我所说的纠结代码。因此,如果您需要更改某个名称,您应该进入所有测试并更改您的补丁,并且没有任何重构工具可以建议您更改 _A__B._B 字符串。

现在,如果你是一个好人并且把你的测试搞得一清二楚,那么你可以只在几个点上出现这些名字,但如果它是一个单例,我敢打赌它会像蘑菇一样被发现。

我想指出 private 和 protected 与某些安全问题无关,它们只是让您的代码更清晰的一种方式。这一点在 Python 中非常清楚,您无需成为黑客即可更改私有(private)或 protected 属性:这些约定在这里只是为了帮助您阅读可以说 Oh great 的代码!我不需要了解它是什么......它只是肮脏的工作。恕我直言,python 中的私有(private)属性无法实现此目标(__ 太长,看到它真的很困扰我)并且 protected 就足够了。

旁注:理解 python 私有(private)命名的小例子:

>>> class A():
... class __B():
... def __c(self):
... pass
...
>>> a = A()
>>> dir(a)
['_A__B', '__doc__', '__module__']
>>> dir(a._A__B)
['_B__c', '__doc__', '__module__']

回到你的案例:你的代码如何使用 __to_be_mocked() 方法?是否可以通过在 A(而不是 A.__A)类中修补/模拟其他东西来产生相同的效果?

最后,如果您正在模拟私有(private)方法来感知要测试的东西,那么您来错地方了:永远不要测试肮脏的工作,它应该/可能/可以在不改变您的测试的情况下改变。您需要的是测试代码行为,而不是代码的编写方式。

protected

如果你需要测试、补丁或模拟 protected 东西,也许你的类隐藏了一些合作者:测试它并使用你的测试来重构你的代码,然后清理你的测试。

免责声明

的确:我在我的测试中散布了这种废话,然后当我明白我可以做得更好时,我会努力将其删除。

关于python - 如何模拟单例类方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35569348/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com