0

Say I have the following:

# maincode.py

from othermodule import do_something

class Myclass():
   @staticmethod
   def return_array():
      array_result = do_something()
      return array_result

   @classmethod
   def main():
       array_result = cls.return_array()
       # other code that uses array_result
# Test.py
# import necessary libraries for mocking

class Test:
    @mock.patch('maincode.Myclass.return_array', autospec=True)
    def test(self, mock_return_array):
        mock_return_array.return_value = ["value1"]
        Myclass.main()

However, I am getting TypeError: 'NonCallableMagicMock' object is not callable

My mock.patch argument points to the correct place, however when I do print(cls.return_array) in main() I'm getting:

<NonCallableMagicMock name='get_exposed_commands' spec='classmethod' id='________'>

Any suggestions on how to fix this? Thanks

Allen Wu
  • 165
  • 1
  • 2
  • 10
  • I would strongly recommend _not_ patching out parts of the thing you're supposed to be testing, in this case the `Myclass` class. Why not `@mock.patch('maincode.do_something')`? – jonrsharpe Jun 19 '21 at 16:51
  • Hi, sorry I should have specified a bit more. In my case the results from the return_array method is being used later on in main_code, and I want to just force that method to return ["value1"] – Allen Wu Jun 19 '21 at 17:23
  • Right, but given that's coming _from_ `do_something`, patching that out instead would allow you to control the value in the tests _without_ having to interfere in the class itself (which adds friction to refactoring later). – jonrsharpe Jun 19 '21 at 17:31
  • The return_array method retrieves the array items from a database which is not available when I run unit tests, so my only option is to patch it – Allen Wu Jun 19 '21 at 17:57
  • 1
    Presumably via `do_something`, so what's the problem? If your [mre] doesn't actually represent your situation, please update it. If you're talking directly to the DB inside that class and don't want that in the test, maybe extract it to a collaborator. – jonrsharpe Jun 19 '21 at 20:06
  • If you wanted to mock individual instance methods, you could do that using patch.object. However when patching a class, as opposed to an instance, with patch I think you can only patch the whole class at a time, so you either patch both main and return_array or none. In this specific scenario I agree with jon that it seems better to patch do_something directly, or maybe separating return_array into a different class and patching that. – Felipe Ferri Jun 22 '21 at 13:51
  • Can't reproduce it. The test case works fine. – Lin Du Jun 29 '21 at 04:24

0 Answers0