2015-09-15 81 views
1

我想要做的事,如下面的例子(發現here使用補丁嘲笑的功能(而不是方法)

>>> with patch.object(ProductionClass, 'method', return_value=None) as mock_method: 
...  thing = ProductionClass() 
...  thing.method(1, 2, 3) 

但是這是在修補叫ProductionClassmethod方法。我想在上下文中修補一個通用函數。理想的東西看起來像......

with path.something(my_fn, return_value=my_return) as mock_function: 
    do_some_other_fn() 

my_fn被稱爲內do_some_other_fn深,因此難以直接模擬出。這似乎應該是簡單的,但我無法找到正確的語法

編輯在模塊do_some_other_fn生活我導入my_fn像以下

from my_module import my_fn 

所以我需要一種方法能夠告訴模擬從模塊外面補丁。這可能嗎?

EDIT 2我想,這使得它更清楚我所期待的

這工作,但並不理想:

import my_module 
with patch('my_module.fn', return_value='hello') as patch_context: 
    x = my_module.fn() 
    # x now contains 'hello' 

但是我寧願有像這樣的工作(或類似的東西)

from my_module import fn 
with patch('my_module.fn', return_value='hello') as patch_context: 
    x = fn() 
    # x contains real result from real call to fn() 

回答

3

你嘗試用from my_module import fn補丁不起作用,因爲import語句創建一個本地符號fn指向任何價值fn在進口的時間已my_module。您稍後補丁my_module.fn但它並不重要,因爲您已有fn的本地副本。

如果包含patch調用該文件的主要模塊(即python最初加載的文件),你應該能夠通過修補__main__.fn做到這一點:

from my_module import fn 
with patch('__main__.fn', return_value='hello') as patch_context: 
    x = fn() 

如果該文件包含patch呼叫作爲模塊從主模塊加載,則__main__將不起作用,並且您需要將包含您的patch調用的模塊的絕對模塊名稱傳遞給patch而不是__main__

0

你可以看到像模塊對象的靜態方法的功能。要在模塊修補功能funcmymodule可以使用

patch("mymodule.func", return_value=my_return) 

你應該好好照顧Where to patch,如果功能是你有測試應該使用"__main__.func"補丁參數相同的模塊中。

patchpatch.object可以用作裝飾器,上下文或通過start()stop()方法。

現在,當一個模塊中,你從其他模塊導入功能,如:

from mymodule import func as foo 

您創建名爲foo新模塊中一個新的參考func每個 您調用foo時您將使用您在導入時加載的對mymodule.func的引用:如果您希望更改此行爲,則應在新模塊中補丁foo

爲了更清楚我建,你有mymodule包含一個例子funcmodule_a包括mymodule和使用mymodule.funcmodule_b使用from mymodule import func as foo和使用機器人foomymodule.func

mymodule.py

def func(): 
    return "orig" 

module_a.py

import mymodule 

def a(): 
    return mymodule.func() 

module_b.py

from mymodule import func as foo 
import mymodule 

def b_foo(): 
    return foo() 

def b(): 
    return mymodule.func() 

test.py

import unittest 
from unittest.mock import * 
import mymodule 
import module_a 
import module_b 

class Test(unittest.TestCase): 
    def test_direct(self): 
     self.assertEqual(mymodule.func(), "orig") 
     with patch("mymodule.func", return_value="patched"): 
      self.assertEqual(mymodule.func(), "patched") 

    def test_module_a(self): 
     self.assertEqual(module_a.a(), "orig") 
     with patch("mymodule.func", return_value="patched"): 
      self.assertEqual(module_a.a(), "patched") 

    def test_module_b(self): 
     self.assertEqual(module_b.b(), "orig") 
     with patch("mymodule.func", return_value="patched"): 
      self.assertEqual(module_b.b(), "patched") 
      self.assertEqual(module_b.b_foo(), "orig") 
     with patch("module_b.foo", return_value="patched"): 
      self.assertEqual(module_b.b(), "orig") 
      self.assertEqual(module_b.b_foo(), "patched")  


if __name__ == '__main__': 
    unittest.main() 

換句話說什麼就選擇在哪裏修補真正的規則是怎樣的功能被引用其中你想使用補丁版本

+0

這個問題的答案。如果使用'patch('mymodule.func'....)'但深入我的代碼中,我使用'from mymodule import func'導入,然後調用'func()',它是否仍然適合修補? – sedavidw

+0

只做過一些測試,看起來不像這樣。如果我執行'mymodule.func',修補程序可以正常工作,但我無法使用'from mymodule import func'。我已經更新了這個問題,以便更清楚地說明 – sedavidw

+0

@sedavidw,正如我在答案中明確指出的那樣,您應該看看https://docs.python.org/3/library/unittest.mock.html#where-補丁。 –