mardi 7 août 2018

How can I call a method on a copied MagicMock in Python?

I want test that a function has called the __copy__ method (with a given set of arguments) on an object that was passed to it.

Since a DB connection is required to create the object, I thought I should mock it and pass the mock to the function for the test.

However, it seems that __copy__ is returning a mock (not sure if Mock or MagicMock) instance that does not allow arbitrary methods to be called on it. Since my code is calling methods on the new object, it returns the error below.

How can I assert that the __copy__ method was called and still have the rest of the function run without error?

FWIW, I tried assigning old_obj.__class__.return_value = MagicMock() but it seems it's not returning what I assign to it (i.e. I also assigned ... = 'foo' but it still returned a mock object).

Example:

from unittest.mock import MagicMock


class MyClass:
    def __init__(self, my_name):
        self.my_name = my_name

    def speak(self):
        print('My name is ' + self.my_name)


def my_func(old_obj, new_name):
    new_obj = old_obj.__class__(new_name)
    new_obj.speak()


def test_my_func():
    old_obj = MagicMock()
    old_obj.my_name = 'foo'

    my_func(old_obj, 'bar')
    enter code here
    enter code here

Error produced by py.test:

self = <MagicMock spec='str' id='4490339552'>, name = 'speak'

    def __getattr__(self, name):
        if name in {'_mock_methods', '_mock_unsafe'}:
            raise AttributeError(name)
        elif self._mock_methods is not None:
            if name not in self._mock_methods or name in _all_magics:
>               raise AttributeError("Mock object has no attribute %r" % name)
E               AttributeError: Mock object has no attribute 'speak'

Aucun commentaire:

Enregistrer un commentaire