在doctest中模拟(from X import Y)的Y(python)

3 投票
2 回答
1525 浏览
提问于 2025-04-15 18:59

我正在尝试创建一个文档测试,里面需要模拟一个在另一个模块中的函数,这个函数是通过下面的方式导入的。

from foomodule import foo

def bar():
    """
    >>> from minimock import mock
    >>> mock('foo', nsdicts=(bar.func_globals,), returns=5)
    >>> bar()
    Called foo()
    10
    """
    return foo() * 2


import doctest
doctest.testmod()

foomodule.py:

def foo():
    raise ValueError, "Don't call me during testing!"

这样做会失败。

如果我把导入改成import foomodule,然后到处使用foomodule.foo,这样就能正常工作了。

但是,有没有什么办法可以模拟以刚才那种方式导入的函数呢?

2 个回答

5

你刚刚遇到了一个很重要的原因,这就是为什么最好不要从模块内部导入对象,而是只从模块本身导入(可能是从包里面)。我们在谷歌的风格指南中把这个规则写进去了(可以在这里找到),我强烈推荐每位Python程序员都遵循这个规则。

话虽如此,你需要做的是把你刚刚用模拟对象替换掉的foomodule.foo放回当前模块。我对doctest的内部机制记得不太清楚,不能确认

   >>> import foomodule
   >>> foo = foomodule.foo

是否足够用——试试看,如果不行,那就用

   >>> import foomodule
   >>> import sys
   >>> sys.modules[__name__].foo = foomodule.foo

是的,这看起来有点乱,但造成这种混乱的原因就是那条看似无害的from foomodule import foo——避免使用它,你的生活会简单很多,工作效率也会提高;-).

2

最后,发现这个问题其实是因为MiniMock的主版本出了问题。旧的稳定版本运行得很正常。

撰写回答