1

patch我在 Fudge 1.0.3 中遇到了装饰器的一种奇怪行为。通过导入类时它不会修补模块

from <module> import <class>

但在导入时工作正常

import <module>

与相应的代码适配。

这是一个最小化的设置:

mdle.py

class Klaas(object):

    def __init__(self):
        # easyest way to signal this class has been instantiated accidently
        raise Exception(">:[")

some.py(测试不工作):

from mdle import Klaas()
def instantiate():
    instance = Klaas()

some.py(测试工作):

import mdle
def instantiate():
    instance = mdle.Klaas()

some_test.py

import unittest
import fudge

import some

class SomeTest(unittest.TestCase):

    @fudge.patch("mdle.Klaas")
    def test_somethingb(self, Klaas_mock):
        klaas_inst = (Klaas_mock.expects_call()
                            .returns_fake())


        # Receiving the exception
        some.instantiate()

我应该以不同的方式修补吗?这是 Fudge 的限制,还是错误?

4

1 回答 1

1

您必须修补引用对象的名称,而不是定义它的位置。

请记住,模块只是具有指向其他对象的名称字典的对象(类也是对象)。同一个对象在不同的​​模块中可以有多个(可能相同的)名称。修补使名称暂时指向 aFake而不是原始对象。

我假设在您的第一个(不工作)some.py模块中,您的意思是:

from mdle import Klass

这将创建一个some.Klass在该模块中使用的名称。默认情况下,该名称恰好与名称匹配mdle,但实际上您有两个名称指向同一个类对象。如果您想使用假的,则需要修补它的名称some,因为这是用于引用被测模块中的类的名称。

您的测试补丁mdle.Klass不是 中使用的名称some,因此您的代码仍然使用其自己的未修补名称来获取真实的类对象。some.Klass在这种情况下,您需要打补丁。

在您的第二个(工作)some.py中,您导入整个mdle模块并使用该模块中的名称引用该类。这就是为什么修补mdle.Klass在这种情况下有效的原因,您正在修补正在使用的名称。

于 2018-03-21T21:24:41.820 回答