8

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!

Nice Guy
  • 479
  • 2
  • 6
  • 12
  • Are you trying to test if `MyClass.foo()` works correctly? Because then you should *not* mock it. – Martijn Pieters Feb 06 '14 at 18:59
  • 2
    No. The idea here in this question is to know how to get the return of that test instead of a MagicMock object, because I would apply this in difference scenarios. There are tests that I need the exactly values in return, not a MagicMock object. – Nice Guy Feb 06 '14 at 19:02
  • I've built an example below; one that does mocks something else, but does set the return value. – Martijn Pieters Feb 06 '14 at 19:06
  • If you really meant to mock `MyClass.foo()`, then your example is overly verbose (and incorrect, there is no `self` on `def TestMyClass()`). You are calling the mock directly, in any case, and the original `MyClass.foo()` is *never* called as it has been replaced by the mock. – Martijn Pieters Feb 06 '14 at 19:08
  • 1
    There's no need to make explicitly call to a class and nor even instantiate it. The mock library makes everything magically. Somehow, following my example code above, after run the test, the foo_mock will be known only as ``. – Nice Guy Feb 06 '14 at 19:43
  • Yes, because you specifically mocked `MyClass`. You replaced the whole class with a mock. Anything you call on a mock, returns another mock unless you specifically set the return value, `MyClassMock.foo.return_value` can be set to something else. But why mock this whole class and then just test the mock? – Martijn Pieters Feb 06 '14 at 19:46
  • Hm, yeah, I got it. That's what I was not understanding. Your last sentence just open my eyes. – Nice Guy Feb 06 '14 at 19:59

1 Answers1

7

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.

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343