Skip to content

Crash in 1.3.x when a cmd2.Cmd method is mocked #981

@tleonhardt

Description

@tleonhardt

If you mock a method within a cmd2 which isn't a command or subcommand method using a MagicMock such as with with mock.patch() or with mock.patch.object(), then things crash because our code thinks it is a subcommand.

Here is a simple unit test that can be added to any of the cmd2 tests files such as test_cmd2.py to reproduce this problem:

class MockMethodApp(cmd2.Cmd):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

    def foo(self):
        pass


def test_mocked_methods():
    with mock.patch.object(MockMethodApp, 'foo'):
        cli = MockMethodApp()

And there is the test failure traceback:

    def test_mocked_methods():
        with mock.patch.object(MockMethodApp, 'foo'):
>           cli = MockMethodApp()

tests/test_cmd2.py:2398: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
tests/test_cmd2.py:2390: in __init__
    super().__init__(*args, **kwargs)
cmd2/cmd2.py:415: in __init__
    self._register_subcommands(self)
cmd2/cmd2.py:646: in _register_subcommands
    command_func = self.cmd_func(command_name)
cmd2/cmd2.py:2406: in cmd_func
    func_name = self._cmd_func_name(command)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <tests.test_cmd2.MockMethodApp object at 0x10c28d8e0>, command = <MagicMock name='foo.parent_command.split().__getitem__()' id='4498776416'>

    def _cmd_func_name(self, command: str) -> str:
        """Get the method name associated with a given command.
    
        :param command: command to look up method name which implements it
        :return: method name which implements the given command
        """
        target = constants.COMMAND_FUNC_PREFIX + command
>       return target if callable(getattr(self, target, None)) else ''
E       TypeError: getattr(): attribute name must be string

cmd2/cmd2.py:2417: TypeError
=============================================================================================== short test summary info ================================================================================================
FAILED tests/test_cmd2.py::test_mocked_methods - TypeError: getattr(): attribute name must be string

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions