0

I'm trying to complete my unit tests for the errbot plugin I am writing. Can anyone tell me how to mock out a helper method which is used by a botcmd method?

Example:

class ChatBot(BotPlugin):

    @classmethod
    def mycommandhelper(cls):
        return 'This is my awesome commandz'

    @botcmd
    def mycommand(self, message, args):
        return self.mycommandhelper()

How can I mock the mycommandhelper class when executing the my command class? In my case this class is performing some remote operations which should not be executed during unit testing.

Tonechas
  • 13,398
  • 16
  • 46
  • 80
DidiV
  • 1

2 Answers2

0

A very simple/crude way would be to simply redefine the function that does the remote operations. Example:

def new_command_helper(cls):
    return 'Mocked!' 

def test(self):
    ch_bot = ChatBot()
    ch_bot.mycommandhelper = new_command_helper
    # Add your test logic

If you'd like to have this method mocked throughout all of your tests, simply do it in the setUp unittest method.

def new_command_helper(cls):
    return 'Mocked!'

class Tests(unittest.TestCase):
    def setUp(self):
        ChatBot.mycommandhelper = new_command_helper
Nether
  • 1,081
  • 10
  • 14
  • I think this would work for 'normal' unit testing however I don't know if this plays nice with the testbot implementation of errbot which gives the functionality to do things like testbot.push_message and testbot.pop_message. Afaik the testbot would not import the mocked class but rather the original class and method of the plugin. – DidiV Jan 25 '17 at 10:56
  • I can't say much more with the limited context/code you gave us. If you were to import the class, mock it (by changing its variables directly) and then import the TestBot, it would import the original class which has been *modified*. – Nether Jan 25 '17 at 12:11
  • Fair enough, the issue here is that this specific framework (errbot) provides a testbot object which loads its plugins dynamically. For this purpose it uses the extra_plugin_dir = '.' which you can see in my example. Therefore modifying the plugin class in the test file doesn't work because the framework will load the unmodified original one afaik. I do appreciate you trying to help and putting effort into this. – DidiV Jan 25 '17 at 13:00
0

After a lot of fiddling around the following seems to work:

class TestChatBot(object):
extra_plugin_dir = '.'

def test_command(self, testbot):
    def othermethod():
        return 'O no'
    plugin = testbot.bot.plugin_manager.get_plugin_obj_by_name('chatbot')
    with mock.patch.object(plugin, 'mycommandhelper') as mock_cmdhelper:
        mock_cmdhelper.return_value = othermethod()
        testbot.push_message('!mycommand')
        assert 'O no' in testbot.pop_message()

Although I believe using patch decorators would be cleaner.

DidiV
  • 1