Mocking Functions Using Python Mock

后端 未结 5 1870
清酒与你
清酒与你 2020-12-01 06:08

I am trying to Mock a function (that returns some external content) using the python mock module.

I\'m having some trouble mocking functions that are im

相关标签:
5条回答
  • 2020-12-01 06:28

    I think I have a workaround, though it's still not quite clear on how to solve the general case

    In mymodule, if I replace

    from util import get_content
    
    class MyObj:    
        def func():
            get_content()
    

    with

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

    The Mock seems to get invoked. It looks like the namespaces need to match (which makes sense). However, the weird thing is that I would expect

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

    to do the trick in the original case where I am using the from/import syntax (which now pulls in get_content into mymodule). But this still refers to the unmocked get_content.

    Turns out the namespace matters - just need to keep that in mind when writing your code.

    0 讨论(0)
  • 2020-12-01 06:41

    Let's assume you're creating your mock inside module foobar:

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

    If you import mymodule and call util.get_content without first importing foobar, your mock will not be installed:

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

    Instead:

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

    Note that foobar can be imported from anywhere (module A imports B which imports foobar) as long as foobar is evaluated before util.get_content is called.

    0 讨论(0)
  • 2020-12-01 06:44

    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.

    0 讨论(0)
  • 2020-12-01 06:49

    You have to patch the function where it is being used. In your case that would be in the mymodule module.

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

    There is a reference in the docs here: http://docs.python.org/dev/library/unittest.mock.html#where-to-patch

    0 讨论(0)
  • 2020-12-01 06:49

    The general case would be to use patch from mock. Consider the following:

    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.

    0 讨论(0)
提交回复
热议问题