我正在使用python mock library開始測試。我想模擬一個在被測模塊的命名空間中導入的模塊,而不需要實際導入它或要求它首先存在(即拋出一個ImportError)。Python:模擬一個模塊,無需導入或需要它存在
假設下面的代碼存在:
foo.py
import helpers
def foo_func():
return helpers.helper_func()
的目標是測試foo_func()的時候 'helpers.py' 不存在任何地方,如果它確實存在,行爲就好像它沒有。
首先嚐試使用超爽@patch裝飾:
from mock import patch, sentinel
import foo
@patch("foo.helpers")
def foo_test(mock):
mock.helper_func.return_value = sentinel.foobar
assert foo.foo_func() == sentinel.foobar
這工作如果「助手」模塊可以導入。如果它不存在,我會得到一個ImportError。
補丁,SANS裝飾下一步嘗試:
from mock import patch, sentinel, Mock
import foo
helpers_mock = patch("foo.helpers")
helpers_mock.start()
def foo_test():
helpers_mock.helper_func = Mock('helper_func')
helpers_mock.helper_func.return_value = sentinel.foobar
assert foo.foo_func() == sentinel.foobar
同樣,這不一樣,如果「助手」缺少工作...,如果它存在,則斷言失敗。不知道爲什麼會發生。
第三次嘗試,當前的解決方案:
import sys
helpers_mock = Mock(name="helpers_mock", spec=['helper_func'])
helpers_mock.__name__ = 'helpers'
sys.modules['helpers'] = helpers_mock
import foo
def foo_test():
helpers_mock.helper_func.return_value = sentinel.foobar
assert foo.foo_func() == sentinel.foobar
此測試通過不管是否 「helpers.py」 是否存在。
這是實現此目標的最佳方式嗎?我正在使用的模擬庫提供了一個替代方案嗎?我可以通過其他方式來做到這一點?
雖然我都是單元測試,但我認爲在這種情況下,您正在測試該語言的一項功能,而不是您的代碼的有用功能。你也可以在foo.py中修改你的導入,這樣一來這個猴子補丁對於一個進口警衛來說是不必要的(例如:try:除了ImportError:helpers = None之外的導入助手,而不是foo.py而不是裸導入)。我的意思是現在foo.py不是寫在一個允許幫助者失蹤,並允許這應該大大簡化您的測試。 – stderr 2011-03-01 06:15:52
我真的很喜歡進口警衛的想法,它解決了很多問題。如果我按照你的建議使用進口警衛,我可以使用我給的第一個例子(@patch裝飾器)。謝謝! – 2011-03-01 07:02:28