9

I have a class, which use a class variable to choose which logic to execute.

#in file1:

class SomeHelper():
    def __init__(self):
        self.my_var = 0

#in file2: 
import file1
class MyClass():
    ...
    ...
    def calculate():
        inst = file1.SomeHelper()
        if x > inst.my_var:
           etc etc

I am writing a unit test and mocking SomeHelper() in another file:

from file 2 import MyClass
# tried both
@patch('file2.file1') OR @patch('file2.file1.SomeHelper')
def test_calculate(self, mock_helper):
    mock_helper.my_var = 0
    to_test = MyClass.calculate()

And I get the following error:

TypeError: '>' not supported between instances of 'MagicMock' and 'int'.

I thought I defined my_var after I patched the module.

3
  • 1
    mock_helper is the whole of file1, you need to be working with mock_helper.SomeHelper().my_var. But note that the complexity of mocking this suggests that you need to apply other patterns, e.g. dependency inversion, to make the code easier to test. Commented May 8, 2018 at 22:12
  • Alas, I tried it and it did not work. Commented May 9, 2018 at 14:15
  • 1
    Kidding - the parenthesis did it. Without (), it was mocking the class rather than instance of class. Thanks! If you post this as an answer, I will accept it. Commented May 9, 2018 at 15:29

1 Answer 1

4

Here is the unit test solution for Python 3.7.5:

file1.py:

class SomeHelper():
    def __init__(self):
        self.my_var = 0

file2.py:

import file1


class MyClass():
    @classmethod
    def calculate(cls):
        x = 1
        inst = file1.SomeHelper()
        if x > inst.my_var:
            return True
        return False

test_file2.py:

import unittest
from unittest.mock import patch
from file2 import MyClass


class TestMyClass(unittest.TestCase):
    @patch('file2.file1')
    def test_calculate(self, mock_file1):
        inst = mock_file1.SomeHelper.return_value
        inst.my_var = 0.5
        to_test = MyClass.calculate()
        self.assertTrue(to_test)
        mock_file1.SomeHelper.assert_called_once()

    @patch('file2.file1')
    def test_calculate_2(self, mock_file1):
        inst = mock_file1.SomeHelper.return_value
        inst.my_var = 2
        to_test = MyClass.calculate()
        self.assertFalse(to_test)
        mock_file1.SomeHelper.assert_called_once()


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

Unit test result with coverage report:

..
----------------------------------------------------------------------
Ran 2 tests in 0.002s

OK
Name                                       Stmts   Miss  Cover   Missing
------------------------------------------------------------------------
src/stackoverflow/50242955/file1.py            3      1    67%   3
src/stackoverflow/50242955/file2.py            8      0   100%
src/stackoverflow/50242955/test_file2.py      16      0   100%
------------------------------------------------------------------------
TOTAL                                         27      1    96%

Source code: https://github.com/mrdulin/python-codelab/tree/master/src/stackoverflow/50242955

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.