簡體   English   中英

使用 Python Mock 模擬函數

[英]Mocking Functions Using Python Mock

我正在嘗試使用 python mock 模塊Mock一個函數(返回一些外部內容)。

我在模擬導入模塊的函數時遇到了一些麻煩。

例如,在util.py我有

def get_content():
  return "stuff"

我想模擬util.get_content以便它返回其他內容。

我正在嘗試這個:

util.get_content=Mock(return_value="mocked stuff")

如果get_content在另一個模塊內被調用,它實際上似乎從未返回模擬對象。 我在如何使用Mock方面缺少一些東西嗎?

請注意,如果我調用以下內容,則一切正常:

>>> util.get_content=Mock(return_value="mocked stuff")
>>> util.get_content()
"mocked stuff"

但是,如果從另一個模塊內部調用get_content ,它將調用原始函數而不是模擬版本:

>>> from mymodule import MyObj
>>> util.get_content=Mock(return_value="mocked stuff")
>>> m=MyObj()
>>> m.func()
"stuff"

mymodule.py內容

from util import get_content

class MyObj:    
    def func():
        get_content()

所以我想我的問題是 - 如何從我調用的模塊內部調用函數的 Mocked 版本?

看來from module import function可能是這里的罪魁禍首,因為它沒有指向 Mocked 函數。

我想我有一個解決方法,雖然它仍然不太清楚如何解決一般情況

mymodule ,如果我更換

from util import get_content

class MyObj:    
    def func():
        get_content()

import util

class MyObj:    
    def func():
        util.get_content()

Mock似乎被調用了。 看起來命名空間需要匹配(這是有道理的)。 然而,奇怪的是,我期望

import mymodule
mymodule.get_content = mock.Mock(return_value="mocked stuff")

在我使用 from/import 語法(現在將get_content拉入mymodule )的原始情況下做這個技巧。 但這仍然是指未模擬的get_content

原來命名空間很重要 - 只需要在編寫代碼時記住這一點。

一般情況是使用mock patch 考慮以下:

實用程序.py

def get_content():
    return 'stuff'

我的模塊.py

from util import get_content


class MyClass(object):

    def func(self):
        return get_content()

測試文件

import unittest

from mock import patch

from mymodule import MyClass

class Test(unittest.TestCase):

    @patch('mymodule.get_content')
    def test_func(self, get_content_mock):
        get_content_mock.return_value = 'mocked stuff'

        my_class = MyClass()
        self.assertEqual(my_class.func(), 'mocked stuff')
        self.assertEqual(get_content_mock.call_count, 1)
        get_content_mock.assert_called_once()

請注意get_content是如何get_content的,它不是util.get_content ,而是mymodule.get_content因為我們在mymodule中使用它。

以上已經用 mock v2.0.0、nosetests v1.3.7 和 python v2.7.9 進行了測試。

您必須修補正在使用的函數。 在您的情況下,這將在 mymodule 模塊中。

import mymodule
>>> mymodule.get_content = Mock(return_value="mocked stuff")
>>> m = mymodule.MyObj()
>>> m.func()
"mocked stuff"

這里的文檔中有一個參考: http : //docs.python.org/dev/library/unittest.mock.html#where-to-patch

假設您正在模塊foobar創建模擬:

import util, mock
util.get_content = mock.Mock(return_value="mocked stuff")

如果您導入mymodule並調用util.get_content而不先導入foobar ,則不會安裝您的模擬:

import util
def func()
    print util.get_content()
func()
"stuff"

反而:

import util
import foobar   # substitutes the mock
def func():
    print util.get_content()
func()
"mocked stuff"

注意, foobar可以從任何地方(模塊A導入B,其進口取得foob​​ar),只要可以導入foobar前計算util.get_content被調用。

雖然它沒有直接為您的問題提供答案,但另一種可能的替代方法是使用 @staticmethod 將您的函數轉換為靜態方法。

因此,您可以使用以下內容將模塊 utils 轉換為類:

class util(object):
     @staticmethod
     def get_content():
         return "stuff"

然后模擬正確地修補它。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM