IT TIP

파이썬 mock을 사용하여 함수 조롱

itqueen 2020. 12. 12. 12:56
반응형

파이썬 mock을 사용하여 함수 조롱


파이썬 모의 모듈 (http://www.voidspace.org.uk/python/mock/index.html)을 사용하여 (외부 콘텐츠를 반환하는) 함수를 모의하려고합니다.

모듈로 가져온 함수를 조롱하는 데 문제가 있습니다.

예를 들어, 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가 조롱 기능을 가리 키지 않는다는 점에서, 여기에 비난 할 수있다.


해결 방법이 있다고 생각하지만 일반적인 경우를 해결하는 방법은 아직 명확하지 않습니다.

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를 참조합니다.

네임 스페이스가 중요하다는 것이 밝혀졌습니다. 코드를 작성할 때 염두에두면됩니다.


사용중인 기능을 패치해야합니다. 귀하의 경우에는 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_contentfoobar

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만큼으로 어디서나 (수입 FOOBAR 모듈 A 수입 B)에서 가져올 수 있습니다 foobar전에 평가가 util.get_content호출된다.


일반적인 경우는에서 사용하는 patchmock입니다. 다음을 고려하세요:

utils.py

def get_content():
    return 'stuff'

mymodule.py

from util import get_content


class MyClass(object):

    def func(self):
        return get_content()

test.py

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()

Note how get_content is mocked, it is not util.get_content, rather mymodule.get_content since we are using it in mymodule.

Above has been tested with mock v2.0.0, nosetests v1.3.7 and python v2.7.9.


While it doesn't provide an answer to your question directly, another possible alternative is to transform your function to a static method using the @staticmethod.

So you could transform your module utils into a class using something like:

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

Then mock patches it correctly.

참고URL : https://stackoverflow.com/questions/5286390/mocking-functions-using-python-mock

반응형