简体   繁体   中英

mocking a return of class object method in python

I would like to mock a method to return a test value in one of my mocked classes. The issue I am running into is rather then returning the test value, the mocked method returns an object of type MagicMock.

The code is pretty contrived but illustrates the issue.

SuT (sut.py):

provider = None


class Provider():
    def get_data(self):
        return 'production data'


def get_provider():
    return Provider()


def setup_provider():
    global provider
    provider = get_provider()


def do_worker():
    return provider.get_data()

Test (mocking.py):

import unittest
from mock import MagicMock
import sut


class TestWorker(unittest.TestCase):
    def test_worker(self):
        provider_mock = MagicMock()
        provider_mock.get_data.return_value = 'test data'

        sut.get_provider = MagicMock(name='get_provider').return_value = provider_mock

        sut.setup_provider()

        data = sut.do_worker()

        # data comes back as type MagicMock
        assert data == 'test data'

You got confused by your chained assignment:

sut.get_provider = MagicMock(name='get_provider').return_value = provider_mock

That assignment binds provider_mock to both sut.get_provider and to MagicMock(name='get_provider').return_value .

In other words, it essentially does this:

sut.get_provider = provider_mock
MagicMock(name='get_provider').return_value = provider_mock

That's not what you wanted. Now sut.get_provider calls provider_mock and returns a new MagicMock object, not the original provider_mock object.

Separate the assignments:

sut.get_provider = MagicMock(name='get_provider')
sut.get_provider.return_value = provider_mock

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM