0

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'
IUnknown
  • 2,596
  • 4
  • 35
  • 52

1 Answers1

2

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
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
  • great thanks - your right I was getting a couple wires crossed - I have spent a lot of time using mocking frameworks in c# and java - still getting my mind wrapped around python. – IUnknown Jul 14 '14 at 18:59