-1

I am trying to mock a class which is instantiated in the constructor of the class I am trying to test. If I define the class I am trying to mock in the same module as the one I am trying to test, everything works fine but when they are in separate modules, I get errors.

Here's my example, taken from here (Note that in my real example, the test class is in a "tests" submodule and the other two files are in "app.src.code..." module.

What am I missing?

helper.py:

import os

class Helper:
    def __init__(self, path):
        self.path = path

    def get_path(self):
        base_path = os.getcwd()
        return os.path.join(base_path, self.path)

worker.py:

from helper import Helper

class Worker:    
    def __init__(self):
        self.helper = Helper('db')

    def work(self):
        path = self.helper.get_path()
        print(f'Working on {path}')
        return path

test_worker.py:

import unittest
from unittest.mock import patch
from worker import Worker


class WorkerTest(unittest.TestCase):
    def test_patching_class(self):
        with patch('helper.Helper') as MockHelper:
            MockHelper.return_value.get_path.return_value = 'testing'
            worker = Worker()
            MockHelper.assert_called_once_with('db')
            self.assertEqual(worker.work(), 'testing')
4
  • 2
    You need to patch the Helper object in worker.py. So try to change your with statement to with patch(worker.Helper) as MockHelper: Commented Apr 3, 2020 at 8:46
  • 1
    Read docs.python.org/3/library/unittest.mock.html#where-to-patch Commented Apr 3, 2020 at 8:47
  • 3
    where is this related to pytest? Commented Apr 3, 2020 at 12:00
  • Thanks @HitLuca this seems to have done the trick Commented Apr 4, 2020 at 7:31

1 Answer 1

2

You need to use the patch decorators to create the mock for the Helper class of the helper.py module.

E.g.

helper.py:

import os


class Helper:
    def __init__(self, path):
        self.path = path

    def get_path(self):
        base_path = os.getcwd()
        return os.path.join(base_path, self.path)

worker.py:

from helper import Helper


class Worker:
    def __init__(self):
        self.helper = Helper('db')

    def work(self):
        path = self.helper.get_path()
        print(f'Working on {path}')
        return path

test_worker.py:

import unittest
from unittest.mock import patch
from worker import Worker


class TestWorker(unittest.TestCase):
    def test_work(self):
        with patch('worker.Helper') as mock_Helper:
            mock_helper_instance = mock_Helper.return_value
            mock_helper_instance.get_path.return_value = 'testing'
            worker = Worker()
            mock_Helper.assert_called_once_with('db')
            self.assertEqual(worker.work(), 'testing')


if __name__ == '__main__':
    unittest.main()

unit test results with coverage report:

Working on testing
.
----------------------------------------------------------------------
Ran 1 test in 0.001s

OK
Name                                        Stmts   Miss  Cover   Missing
-------------------------------------------------------------------------
src/stackoverflow/61008064/helper.py            7      3    57%   6, 9-10
src/stackoverflow/61008064/test_worker.py      13      0   100%
src/stackoverflow/61008064/worker.py            8      0   100%
-------------------------------------------------------------------------
TOTAL                                          28      3    89%
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.