Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python Mock - How to get the return of a MagicMock as if it was a normal method

For example:

import mock

class MyClass(object):
    def foo(self, x, y, z):
        return (x, y, z)


class TestMyClass(TestCase)
    @mock.patch('MyClass')
    def TestMyClass(self, MyClassMock):
        foo_mock = MyClassMock.foo()

        self.assertEquals((x, y, z), foo_mock)

So, the real question is: How to get the return of that test intead of getting this <MagicMock name='MyClass.foo()' id='191728464'> or how to deal with this MagicMock object to get the return of that test which should be a tuple containing 3 elements and nothing more or less?

Any suggestion, any idea, any argument will be welcome. Thanks in advance!

like image 416
Nice Guy Avatar asked Feb 06 '14 18:02

Nice Guy


People also ask

What is the difference between MagicMock and mock?

So what is the difference between them? MagicMock is a subclass of Mock . It contains all magic methods pre-created and ready to use (e.g. __str__ , __len__ , etc.). Therefore, you should use MagicMock when you need magic methods, and Mock if you don't need them.

How do you mock a value in Python?

How do we mock in Python? Mocking in Python is done by using patch to hijack an API function or object creation call. When patch intercepts a call, it returns a MagicMock object by default. By setting properties on the MagicMock object, you can mock the API call to return any value you want or raise an Exception .

What is side effect in Python mock?

Side Effects These are the things that you want to happen when your mock function is called. Common examples are calling another function or raising exceptions.

How do you mock a class object in Unittest Python?

The patch() decorators makes it easy to temporarily replace classes in a particular module with a Mock object. By default patch() will create a MagicMock for you. You can specify an alternative class of Mock using the new_callable argument to patch() . Create a new Mock object.


1 Answers

If you trying to test if MyClass.foo() works correctly, you should not mock it.

Mocking is used for anything outside the code-under-test; if foo called another, external function some_module.bar(), then you'd mock some_module.bar() and give it a staged return value:

import some_module

class MyClass(object):
    def foo(self, x, y, z):
        result = some_module.bar(x, y, z)
        return result[0] + 2, result[1] * 2, result[2] - 2

class TestMyClass(TestCase):
    @mock.patch('some_module.bar')
    def test_myclass(self, mocked_bar):
        mocked_bar.return_value = (10, 20, 30)

        mc = MyClass()

        # calling MyClass.foo returns a result based on bar()
        self.assertEquals(mc.foo('spam', 'ham', 'eggs'),
            (12, 40, 28))
        # some_class.bar() was called with the original arguments
        mocked_bar.assert_called_with('spam', 'ham', 'eggs')

Here I set mocked_bar.return_value to what should be returned when the mocked some_module.bar() function is called. When the code-under-test actually calls bar(), the mock returns that value.

When you don't set a return_value a new MagicMock() object is returned instead, one that'll support further calls, and you can test for those calls just like on the mocked_bar object, etc.

like image 62
Martijn Pieters Avatar answered Oct 08 '22 21:10

Martijn Pieters