最近的單元測試中,使用mock模組時發現乙個乙個奇怪的問題,當使用from module import func
後,如果使用mock去模擬對應的方法時,執行的依舊是原始方法,而不是模擬的方法。下面使用**解釋一下:
在專案中存在三個python檔案,其中乙個是action.py
檔案,**為:
def func():
return 'original func'
第二個是execute_to_action.py
檔案,其**檔案為:
from action import func
def my_func():
return func()
另乙個是test.py
檔案,其**檔案為:
import unittest
from mock import patch
from execute_to_action import my_func
class mytestcase(unittest.testcase):
@patch('action.func')
def test_func(self, mock_func):
mock_func.return_value = 'new value'
result = my_func()
print(result)
if __name__ == '__main__':
unittest.main()
使用pytest執行上面的測試**,最終執行的結果是original func
,說明mock沒有成功
但是採用另一種引入方式,將action.py
修改為如下所示:
import action
def my_func():
return action.func()
執行結果是new value
,說明這種方式是可以正常mock成功的。
按照之前使用的情況來看,import module
和from module import func
是類似,但是從mock的情況來看,這兩種使用方式存在一些細微的區別,那麼區別到底是什麼呢?
一般搜尋之後,這兩種方式執行的操作是不同的。
所以這兩種引入造成的區別是命名空間的不同,因此import的不同結果可能就是命名空間造成的。可以做出如下的解釋:
採用import module
引入時,會根據原始action模組建立命名空間,呼叫my_func()
方法時,是在原始的命名空間下執行的,而mock中的patch()
方法使用的就是原始action模組對應命名空間,因此這種方式是可以正常模擬的。
採用from module import func
的方式引入時,會將原始方法載入到當前test模組的命名空間中,而mock中的patch()
方法中使用的還是原始action模組對應的命名空間,因此這種方式不能正確模擬方法。
那麼如何驗證這種猜測呢,既然from module import func
是將原始方法載入到當前test模組的命名空間中,可以在mock的patch()
方法中模擬的當前test模組的my_func()
方法,應該就可以正常工作了。那麼將execute_to_action.py
恢復原始狀態,test.py
的**修改為如下所示:
import unittest
from mock import patch
from execute_to_action import my_func
class mytestcase(unittest.testcase):
@patch('execute_to_action.func')
def test_func(self, mock_func):
mock_func.return_value = 'new value'
result = my_func()
print(result)
if __name__ == '__main__':
unittest.main()
測試結果是new value
,說明猜測正確
這個問題還是對python的引入機制了解不夠深入造成的。下面詳細介紹一下:
參考:
jquery ajax return不起作用
最近做專案時,發現乙個問題,但卻不知道怎麼改,耐著性子問了一下午的度娘,終於找到答案 問題 jquery ajax提交,return值一直都無法獲取 原因 ajax請求和後面的處理是非同步執行的,也就是說,有可能ajax還沒執行完,還沒走到return的部分,ajax請求後面的 已經執行完畢 所以a...
setMargins不起作用
在用viewpage做廣告滾動的效果,根據 的數量,每個 生成乙個圓點用來表示,當前 滾動的位置,但是用layoutparams 物件設定圓點的高和寬都正常,用setmargins設定圓點的間距卻無效,請高手解答 private void initui context context else ml...
gitignore不起作用
gitignore中已經標明忽略的檔案目錄下的檔案,git push的時候還會出現在push的目錄中,原因是因為在git忽略目錄中,新建的檔案在git中會有快取,如果某些檔案已經被納入了版本管理中,就算是在.gitignore中已經宣告了忽略路徑也是不起作用的,這時候我們就應該先把本地快取刪除,然後...